2016-08-16 00:09:55 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* proclist.h
|
|
|
|
* operations on doubly-linked lists of pgprocnos
|
|
|
|
*
|
|
|
|
* The interface is similar to dlist from ilist.h, but uses pgprocno instead
|
|
|
|
* of pointers. This allows proclist_head to be mapped at different addresses
|
|
|
|
* in different backends.
|
|
|
|
*
|
|
|
|
* See proclist_types.h for the structs that these functions operate on. They
|
|
|
|
* are separated to break a header dependency cycle with proc.h.
|
|
|
|
*
|
2024-01-04 02:49:05 +01:00
|
|
|
* Portions Copyright (c) 2016-2024, PostgreSQL Global Development Group
|
2016-08-16 00:09:55 +02:00
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/include/storage/proclist.h
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifndef PROCLIST_H
|
|
|
|
#define PROCLIST_H
|
|
|
|
|
|
|
|
#include "storage/proc.h"
|
|
|
|
#include "storage/proclist_types.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize a proclist.
|
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
proclist_init(proclist_head *list)
|
|
|
|
{
|
2024-03-03 18:38:22 +01:00
|
|
|
list->head = list->tail = INVALID_PROC_NUMBER;
|
2016-08-16 00:09:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Is the list empty?
|
|
|
|
*/
|
|
|
|
static inline bool
|
2023-01-19 09:45:34 +01:00
|
|
|
proclist_is_empty(const proclist_head *list)
|
2016-08-16 00:09:55 +02:00
|
|
|
{
|
2024-03-03 18:38:22 +01:00
|
|
|
return list->head == INVALID_PROC_NUMBER;
|
2016-08-16 00:09:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a pointer to a proclist_node inside a given PGPROC, given a procno and
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
* the proclist_node field's offset within struct PGPROC.
|
2016-08-16 00:09:55 +02:00
|
|
|
*/
|
|
|
|
static inline proclist_node *
|
|
|
|
proclist_node_get(int procno, size_t node_offset)
|
|
|
|
{
|
|
|
|
char *entry = (char *) GetPGProcByNumber(procno);
|
|
|
|
|
|
|
|
return (proclist_node *) (entry + node_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
* Insert a process at the beginning of a list.
|
2016-08-16 00:09:55 +02:00
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
proclist_push_head_offset(proclist_head *list, int procno, size_t node_offset)
|
|
|
|
{
|
|
|
|
proclist_node *node = proclist_node_get(procno, node_offset);
|
|
|
|
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
Assert(node->next == 0 && node->prev == 0);
|
|
|
|
|
2024-03-03 18:38:22 +01:00
|
|
|
if (list->head == INVALID_PROC_NUMBER)
|
2016-08-16 00:09:55 +02:00
|
|
|
{
|
2024-03-03 18:38:22 +01:00
|
|
|
Assert(list->tail == INVALID_PROC_NUMBER);
|
|
|
|
node->next = node->prev = INVALID_PROC_NUMBER;
|
2016-08-16 00:09:55 +02:00
|
|
|
list->head = list->tail = procno;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-03-03 18:38:22 +01:00
|
|
|
Assert(list->tail != INVALID_PROC_NUMBER);
|
2016-11-22 20:26:40 +01:00
|
|
|
Assert(list->head != procno);
|
|
|
|
Assert(list->tail != procno);
|
2016-08-16 00:09:55 +02:00
|
|
|
node->next = list->head;
|
|
|
|
proclist_node_get(node->next, node_offset)->prev = procno;
|
2024-03-03 18:38:22 +01:00
|
|
|
node->prev = INVALID_PROC_NUMBER;
|
2016-08-16 00:09:55 +02:00
|
|
|
list->head = procno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
* Insert a process at the end of a list.
|
2016-08-16 00:09:55 +02:00
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
proclist_push_tail_offset(proclist_head *list, int procno, size_t node_offset)
|
|
|
|
{
|
|
|
|
proclist_node *node = proclist_node_get(procno, node_offset);
|
|
|
|
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
Assert(node->next == 0 && node->prev == 0);
|
|
|
|
|
2024-03-03 18:38:22 +01:00
|
|
|
if (list->tail == INVALID_PROC_NUMBER)
|
2016-08-16 00:09:55 +02:00
|
|
|
{
|
2024-03-03 18:38:22 +01:00
|
|
|
Assert(list->head == INVALID_PROC_NUMBER);
|
|
|
|
node->next = node->prev = INVALID_PROC_NUMBER;
|
2016-08-16 00:09:55 +02:00
|
|
|
list->head = list->tail = procno;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-03-03 18:38:22 +01:00
|
|
|
Assert(list->head != INVALID_PROC_NUMBER);
|
2016-11-22 20:26:40 +01:00
|
|
|
Assert(list->head != procno);
|
|
|
|
Assert(list->tail != procno);
|
2016-08-16 00:09:55 +02:00
|
|
|
node->prev = list->tail;
|
|
|
|
proclist_node_get(node->prev, node_offset)->next = procno;
|
2024-03-03 18:38:22 +01:00
|
|
|
node->next = INVALID_PROC_NUMBER;
|
2016-08-16 00:09:55 +02:00
|
|
|
list->tail = procno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
* Delete a process from a list --- it must be in the list!
|
2016-08-16 00:09:55 +02:00
|
|
|
*/
|
|
|
|
static inline void
|
|
|
|
proclist_delete_offset(proclist_head *list, int procno, size_t node_offset)
|
|
|
|
{
|
|
|
|
proclist_node *node = proclist_node_get(procno, node_offset);
|
|
|
|
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
Assert(node->next != 0 || node->prev != 0);
|
|
|
|
|
2024-03-03 18:38:22 +01:00
|
|
|
if (node->prev == INVALID_PROC_NUMBER)
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
{
|
|
|
|
Assert(list->head == procno);
|
2016-08-16 00:09:55 +02:00
|
|
|
list->head = node->next;
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
}
|
2016-08-16 00:09:55 +02:00
|
|
|
else
|
|
|
|
proclist_node_get(node->prev, node_offset)->next = node->next;
|
|
|
|
|
2024-03-03 18:38:22 +01:00
|
|
|
if (node->next == INVALID_PROC_NUMBER)
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
{
|
|
|
|
Assert(list->tail == procno);
|
2016-08-16 00:09:55 +02:00
|
|
|
list->tail = node->prev;
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
}
|
2016-08-16 00:09:55 +02:00
|
|
|
else
|
|
|
|
proclist_node_get(node->next, node_offset)->prev = node->prev;
|
2016-11-22 20:26:40 +01:00
|
|
|
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
node->next = node->prev = 0;
|
2016-11-22 20:26:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
* Check if a process is currently in a list. It must be known that the
|
|
|
|
* process is not in any _other_ proclist that uses the same proclist_node,
|
|
|
|
* so that the only possibilities are that it is in this list or none.
|
2016-11-22 20:26:40 +01:00
|
|
|
*/
|
|
|
|
static inline bool
|
2023-01-19 09:45:34 +01:00
|
|
|
proclist_contains_offset(const proclist_head *list, int procno,
|
2016-11-22 20:26:40 +01:00
|
|
|
size_t node_offset)
|
|
|
|
{
|
2023-01-19 09:45:34 +01:00
|
|
|
const proclist_node *node = proclist_node_get(procno, node_offset);
|
2016-11-22 20:26:40 +01:00
|
|
|
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
/* If it's not in any list, it's definitely not in this one. */
|
2016-11-22 20:26:40 +01:00
|
|
|
if (node->prev == 0 && node->next == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
* It must, in fact, be in this list. Ideally, in assert-enabled builds,
|
|
|
|
* we'd verify that. But since this function is typically used while
|
|
|
|
* holding a spinlock, crawling the whole list is unacceptable. However,
|
|
|
|
* we can verify matters in O(1) time when the node is a list head or
|
|
|
|
* tail, and that seems worth doing, since in practice that should often
|
|
|
|
* be enough to catch mistakes.
|
2016-11-22 20:26:40 +01:00
|
|
|
*/
|
2024-03-03 18:38:22 +01:00
|
|
|
Assert(node->prev != INVALID_PROC_NUMBER || list->head == procno);
|
|
|
|
Assert(node->next != INVALID_PROC_NUMBER || list->tail == procno);
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
|
|
|
|
return true;
|
2016-11-22 20:26:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
* Remove and return the first process from a list (there must be one).
|
2016-11-22 20:26:40 +01:00
|
|
|
*/
|
|
|
|
static inline PGPROC *
|
|
|
|
proclist_pop_head_node_offset(proclist_head *list, size_t node_offset)
|
|
|
|
{
|
|
|
|
PGPROC *proc;
|
|
|
|
|
|
|
|
Assert(!proclist_is_empty(list));
|
|
|
|
proc = GetPGProcByNumber(list->head);
|
|
|
|
proclist_delete_offset(list, list->head, node_offset);
|
|
|
|
return proc;
|
2016-08-16 00:09:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper macros to avoid repetition of offsetof(PGPROC, <member>).
|
|
|
|
* 'link_member' is the name of a proclist_node member in PGPROC.
|
|
|
|
*/
|
|
|
|
#define proclist_delete(list, procno, link_member) \
|
|
|
|
proclist_delete_offset((list), (procno), offsetof(PGPROC, link_member))
|
|
|
|
#define proclist_push_head(list, procno, link_member) \
|
|
|
|
proclist_push_head_offset((list), (procno), offsetof(PGPROC, link_member))
|
|
|
|
#define proclist_push_tail(list, procno, link_member) \
|
|
|
|
proclist_push_tail_offset((list), (procno), offsetof(PGPROC, link_member))
|
2016-11-22 20:26:40 +01:00
|
|
|
#define proclist_pop_head_node(list, link_member) \
|
|
|
|
proclist_pop_head_node_offset((list), offsetof(PGPROC, link_member))
|
|
|
|
#define proclist_contains(list, procno, link_member) \
|
|
|
|
proclist_contains_offset((list), (procno), offsetof(PGPROC, link_member))
|
2016-08-16 00:09:55 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Iterate through the list pointed at by 'lhead', storing the current
|
|
|
|
* position in 'iter'. 'link_member' is the name of a proclist_node member in
|
|
|
|
* PGPROC. Access the current position with iter.cur.
|
|
|
|
*
|
|
|
|
* The only list modification allowed while iterating is deleting the current
|
|
|
|
* node with proclist_delete(list, iter.cur, node_offset).
|
|
|
|
*/
|
|
|
|
#define proclist_foreach_modify(iter, lhead, link_member) \
|
|
|
|
for (AssertVariableIsOfTypeMacro(iter, proclist_mutable_iter), \
|
|
|
|
AssertVariableIsOfTypeMacro(lhead, proclist_head *), \
|
|
|
|
(iter).cur = (lhead)->head, \
|
2024-03-03 18:38:22 +01:00
|
|
|
(iter).next = (iter).cur == INVALID_PROC_NUMBER ? INVALID_PROC_NUMBER : \
|
2016-08-16 00:09:55 +02:00
|
|
|
proclist_node_get((iter).cur, \
|
|
|
|
offsetof(PGPROC, link_member))->next; \
|
2024-03-03 18:38:22 +01:00
|
|
|
(iter).cur != INVALID_PROC_NUMBER; \
|
2016-08-16 00:09:55 +02:00
|
|
|
(iter).cur = (iter).next, \
|
2024-03-03 18:38:22 +01:00
|
|
|
(iter).next = (iter).cur == INVALID_PROC_NUMBER ? INVALID_PROC_NUMBER : \
|
2016-08-16 00:09:55 +02:00
|
|
|
proclist_node_get((iter).cur, \
|
|
|
|
offsetof(PGPROC, link_member))->next)
|
|
|
|
|
Improve error detection capability in proclists.
Previously, although the initial state of a proclist_node is expected
to be next == prev == 0, proclist_delete_offset would reset nodes to
next == prev == INVALID_PGPROCNO when removing them from a list.
This is the same state that a node in a singleton list has, so that
it's impossible to distinguish not-in-a-list from in-a-list. Change
proclist_delete_offset to reset removed nodes to next == prev == 0,
making it possible to distinguish those cases, and then add Asserts
to the list add and delete functions that the supplied node isn't
or is in a list at entry. Also tighten assertions about the node
being in the particular list (not some other one) where it is possible
to check that in O(1) time.
In ConditionVariablePrepareToSleep, since we don't expect the process's
cvWaitLink to already be in a list, remove the more-or-less-useless
proclist_contains check; we'd rather have proclist_push_tail's new
assertion fire if that happens.
Improve various comments related to proclists, too.
Patch by me, reviewed by Thomas Munro. This isn't back-patchable, since
there could theoretically be inlined copies of proclist_delete_offset in
third-party modules. But it's only improving debuggability anyway.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-09 00:07:04 +01:00
|
|
|
#endif /* PROCLIST_H */
|