Home | History | Annotate | Download | only in kern
History log of /src/sys/kern/subr_pcq.c
RevisionDateAuthorComments
 1.20  24-Feb-2023  riastradh kern: Eliminate most __HAVE_ATOMIC_AS_MEMBAR conditionals.

I'm leaving in the conditional around the legacy membar_enters
(store-before-load, store-before-store) in kern_mutex.c and in
kern_lock.c because they may still matter: store-before-load barriers
tend to be the most expensive kind, so eliding them is probably
worthwhile on x86. (It also may not matter; I just don't care to do
measurements right now, and it's a single valid and potentially
justifiable use case in the whole tree.)

However, membar_release/acquire can be mere instruction barriers on
all TSO platforms including x86, so there's no need to go out of our
way with a bad API to conditionalize them. If the procedure call
overhead is measurable we just could change them to be macros on x86
that expand into __insn_barrier.

Discussed on tech-kern:
https://mail-index.netbsd.org/tech-kern/2023/02/23/msg028729.html
 1.19  23-Feb-2023  riastradh pcq(9): KASSERT(A && B) -> KASSERT(A); KASSERT(B)
 1.18  23-Feb-2023  riastradh pcq(9): Sketch correctness proof for some critical properties.

No functional change intended.
 1.17  23-Feb-2023  riastradh pcq(9): Explain why membar_release isn't needed in pcq_get.

No functional change intended.
 1.16  23-Feb-2023  riastradh pcq(9): Explain why store need not be atomic in pcq_get.

No functional change intended.
 1.15  23-Feb-2023  riastradh pcq(9): Fix consume operation in pcq_peek/get.

These use atomic_load_consume to match the atomic_store_release in
pcq_put for pcq->pcq_items[c].

Reading the snapshot of pcq->pcq_pc need not be ordered:

- The consumer side (pcq_peek/get) is serialized by the API contract
(single-consumer, multi-producer), so no ordering is necessary.

- The producer side updates pcq->pcq_pc first; if the consumer side
sees that before the producer side has stored pcq->pcq_items[c],
there's no problem -- it's as if the consumer had happened just a
moment earlier and the producer hadn't entered pcq_put yet.

However, it should be an atomic load, not a plain load. So use
atomic_load_relaxed, if for no other reason than to pacify thread
sanitizers.

XXX pullup-9
XXX pullup-10
 1.14  23-Feb-2023  riastradh pcq(9): Make pcq_put a release operation, in memory ordering.

Otherwise, for example, the following assertion could fail:

/* publisher */
nusers = foo->nusers;
pcq_put(pcq, foo);
KASSERT(nusers == 0);

/* user */
foo = pcq_get(pcq);
if (foo != NULL)
atomic_inc_uint(&foo->nusers);

XXX pullup-9
XXX pullup-10
 1.13  08-Feb-2021  wiz branches: 1.13.18;
Fix typo in comment.
 1.12  12-Jan-2021  skrll Typo in comment
 1.11  16-Dec-2019  ad branches: 1.11.8;
pcq_create(): fix broken assertion.
 1.10  08-Feb-2018  dholland branches: 1.10.4;
Typos.
 1.9  08-Jan-2015  riastradh Use membar_datadep_consumer where code inspection reveals it necessary.
 1.8  09-Jun-2014  rmind branches: 1.8.4;
Add PCQ_MAXLEN constant.
 1.7  06-Feb-2014  riastradh branches: 1.7.2;
__HAVE_ATOMIC_AS_MEMBAR is spelled with two leading underscores.

This underscores the need to replace this error-prone cpp API by
unconditionally defined {pre,post}atomic_membar_*.

This change should only remove unnecessary membar_producers on x86.
 1.6  31-Jan-2012  alnsn branches: 1.6.2; 1.6.6; 1.6.10;
Revert to more readable but non-standard use of offsetof to calculate
a size of a structure with a flexible array member.
 1.5  31-Jan-2012  alnsn Replace offsetof(pcq_t, pcq_items[nitems]) with sizeof(pcq_t) + sizeof(void *[nitems]).
 1.4  22-Jan-2012  rmind Replace pcq(9) with the implementation from ad@ and minor changes by me.

PR/40516, PR/45631.
 1.3  11-Nov-2008  rmind branches: 1.3.4; 1.3.6; 1.3.8; 1.3.12; 1.3.24; 1.3.28;
- Optimise by avoiding few memory barriers, when atomic operations
performs that for us. OK by <matt>.
- Add RCS ID, and a bit of KNF.
 1.2  11-Nov-2008  snj Fix a couple spelling mistakes in comments.
 1.1  11-Nov-2008  matt Add generic producer/consumer queue code.
 1.3.28.1  18-Feb-2012  mrg merge to -current.
 1.3.24.2  22-May-2014  yamt sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs. ("Protocol error: too many arguments")
 1.3.24.1  17-Apr-2012  yamt sync with head
 1.3.12.2  04-May-2009  yamt sync with head.
 1.3.12.1  11-Nov-2008  yamt file subr_pcq.c was added on branch yamt-nfs-mp on 2009-05-04 08:13:48 +0000
 1.3.8.2  19-Jan-2009  skrll Sync with HEAD.
 1.3.8.1  11-Nov-2008  skrll file subr_pcq.c was added on branch nick-hppapmap on 2009-01-19 13:19:39 +0000
 1.3.6.2  17-Jan-2009  mjf Sync with HEAD.
 1.3.6.1  11-Nov-2008  mjf file subr_pcq.c was added on branch mjf-devfs2 on 2009-01-17 13:29:19 +0000
 1.3.4.2  13-Dec-2008  haad Update haad-dm branch to haad-dm-base2.
 1.3.4.1  11-Nov-2008  haad file subr_pcq.c was added on branch haad-dm on 2008-12-13 01:15:08 +0000
 1.6.10.1  18-May-2014  rmind sync with head
 1.6.6.2  03-Dec-2017  jdolecek update from HEAD
 1.6.6.1  20-Aug-2014  tls Rebase to HEAD as of a few days ago.
 1.6.2.1  27-Oct-2014  msaitoh Pull up following revision(s) (requested by riastradh in ticket #1132):
sys/kern/subr_pcq.c: revision 1.7
__HAVE_ATOMIC_AS_MEMBAR is spelled with two leading underscores.
This underscores the need to replace this error-prone cpp API by
unconditionally defined {pre,post}atomic_membar_*.
This change should only remove unnecessary membar_producers on x86.
 1.7.2.1  10-Aug-2014  tls Rebase.
 1.8.4.1  06-Apr-2015  skrll Sync with HEAD
 1.10.4.1  08-Apr-2020  martin Merge changes from current as of 20200406
 1.11.8.1  03-Apr-2021  thorpej Sync with HEAD.
 1.13.18.1  30-Jul-2023  martin Pull up following revision(s) (requested by riastradh in ticket #263):

share/man/man9/pcq.9: revision 1.9
sys/kern/subr_pcq.c: revision 1.14
sys/kern/subr_pcq.c: revision 1.15
sys/kern/subr_pcq.c: revision 1.16
sys/kern/subr_pcq.c: revision 1.17
sys/kern/subr_pcq.c: revision 1.18
sys/kern/subr_pcq.c: revision 1.19

pcq(9): Make pcq_put a release operation, in memory ordering.

Otherwise, for example, the following assertion could fail:
/* publisher */
nusers = foo->nusers;
pcq_put(pcq, foo);
KASSERT(nusers == 0);
/* user */
foo = pcq_get(pcq);
if (foo != NULL)
atomic_inc_uint(&foo->nusers);


pcq(9): Fix consume operation in pcq_peek/get.

These use atomic_load_consume to match the atomic_store_release in
pcq_put for pcq->pcq_items[c].

Reading the snapshot of pcq->pcq_pc need not be ordered:
- The consumer side (pcq_peek/get) is serialized by the API contract
(single-consumer, multi-producer), so no ordering is necessary.
- The producer side updates pcq->pcq_pc first; if the consumer side
sees that before the producer side has stored pcq->pcq_items[c],
there's no problem -- it's as if the consumer had happened just a
moment earlier and the producer hadn't entered pcq_put yet.

However, it should be an atomic load, not a plain load. So use
atomic_load_relaxed, if for no other reason than to pacify thread
sanitizers.


pcq(9): Explain why store need not be atomic in pcq_get.
No functional change intended.

pcq(9): Explain why membar_release isn't needed in pcq_get.
No functional change intended.

pcq(9): Document memory ordering guarantees.

pcq(9): Sketch correctness proof for some critical properties.
No functional change intended.

pcq(9): KASSERT(A && B) -> KASSERT(A); KASSERT(B)

RSS XML Feed