All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Zbigniew Kempczyński" <zbigniew.kempczynski@intel.com>
To: Jason Ekstrand <jason@jlekstrand.net>
Cc: IGT GPU Tools <igt-dev@lists.freedesktop.org>
Subject: Re: [igt-dev] [PATCH i-g-t v26 02/35] lib/igt_list: igt_hlist implementation.
Date: Wed, 17 Mar 2021 20:13:15 +0100	[thread overview]
Message-ID: <20210317191315.GA123572@zkempczy-mobl2> (raw)
In-Reply-To: <CAOFGe97q-jCFTBV-6KL6K5n5_cJDnLms55qEhf0J9RE7C1=CeA@mail.gmail.com>

On Wed, Mar 17, 2021 at 01:02:53PM -0500, Jason Ekstrand wrote:
> On Wed, Mar 17, 2021 at 12:43 PM Zbigniew Kempczyński
> <zbigniew.kempczynski@intel.com> wrote:
> >
> > On Wed, Mar 17, 2021 at 11:43:38AM -0500, Jason Ekstrand wrote:
> > > Would it be better to pull the hash table implementation from Mesa?
> > > Or use https://cgit.freedesktop.org/~anholt/hash_table/ which should
> > > be identical, though it may be a bit out-of-date.  I've poured enough
> > > hours of my life into finding and fixing the bugs in the Mesa hash
> > > table that IGT rolling its own doesn't really fill me with happy
> > > feelings.
> > >
> > > --Jason
> >
> > I'm not going to be a devil advocate, I'll just ask Dominik how
> > confident is he about that implementation, at least we can provide
> > some stress test with multithreading scenarios.
> >
> > He's ported kernel hashtable so if he didn't introduce a non obvious
> > bug it should work.
> 
> If this is, indeed, a port of the kernel hash table, then it's
> probably ok.  Not sure how that works out on licenses, but it should
> be correct.  If this has been freshly hand-rolled expressly for this
> purpose, then it makes me nervous.
> 
> > Regarding Eric implementation - we need to adopt that implementation
> > to at least rename to igt_* and fix the code which is using.
> > Should take few days max.
> >
> > If you'll take a look to tests api_intel_allocator@two-level-inception
> > you'll see we're stress testing that hashtable much from many
> > processes / threads and we see no problem with losing data coherency
> > in the map.
> 
> I'm less worried about threads, so long as it's locked, as I am about
> weird insert/remove patterns.  Most of the bugs I've had to fix in
> mesa were because certain patterns of insert/remove with the right
> hashes would cause it to blow up.  If most of what you do is just add
> a bunch of stuff without a lot of removal, they can be unlikely and
> hard to find.  That said, given that it's linked list based and not
> re-hash based, a lot of those corner cases are less likely than they
> were with the Mesa implementation.  Again, my primary concern is with
> a NEW hash table impl. :-)

I'm not sure I've understand you correctly - it is re-hash based (see
igt_map_extend()), and it grows if necessary. Works properly when you
don't forget about locking during operations (not only add, but find
too because it is not funny when someone is taking the rug from under
your feet).

All multiprocess/multithread tests in api_intel_allocator heavily
exercise insert/remove scenarios (open/close allocator just give 
you new handle inserted/removed from handles hash table so lack 
of consistency would be quickly fount imo).

--
Zbigniew

> 
> --Jason
> 
> > --
> > Zbigniew
> > >
> > > On Wed, Mar 17, 2021 at 9:46 AM Zbigniew Kempczyński
> > > <zbigniew.kempczynski@intel.com> wrote:
> > > >
> > > > From: Dominik Grzegorzek <dominik.grzegorzek@intel.com>
> > > >
> > > > Double linked lists with a single pointer list head implementation,
> > > > based on similar in the kernel.
> > > >
> > > > Signed-off-by: Dominik Grzegorzek <dominik.grzegorzek@intel.com>
> > > > Cc: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> > > > Cc: Chris Wilson <chris@chris-wilson.co.uk>
> > > > Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> > > > ---
> > > >  lib/igt_list.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  lib/igt_list.h | 50 +++++++++++++++++++++++++++++++++--
> > > >  2 files changed, 120 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/lib/igt_list.c b/lib/igt_list.c
> > > > index 37ae139c4..43200f9b3 100644
> > > > --- a/lib/igt_list.c
> > > > +++ b/lib/igt_list.c
> > > > @@ -22,6 +22,7 @@
> > > >   *
> > > >   */
> > > >
> > > > +#include "assert.h"
> > > >  #include "igt_list.h"
> > > >
> > > >  void IGT_INIT_LIST_HEAD(struct igt_list_head *list)
> > > > @@ -81,3 +82,74 @@ bool igt_list_empty(const struct igt_list_head *head)
> > > >  {
> > > >         return head->next == head;
> > > >  }
> > > > +
> > > > +void igt_hlist_init(struct igt_hlist_node *h)
> > > > +{
> > > > +       h->next = NULL;
> > > > +       h->pprev = NULL;
> > > > +}
> > > > +
> > > > +int igt_hlist_unhashed(const struct igt_hlist_node *h)
> > > > +{
> > > > +       return !h->pprev;
> > > > +}
> > > > +
> > > > +int igt_hlist_empty(const struct igt_hlist_head *h)
> > > > +{
> > > > +       return !h->first;
> > > > +}
> > > > +
> > > > +static void __igt_hlist_del(struct igt_hlist_node *n)
> > > > +{
> > > > +       struct igt_hlist_node *next = n->next;
> > > > +       struct igt_hlist_node **pprev = n->pprev;
> > > > +
> > > > +       *pprev = next;
> > > > +       if (next)
> > > > +               next->pprev = pprev;
> > > > +}
> > > > +
> > > > +void igt_hlist_del(struct igt_hlist_node *n)
> > > > +{
> > > > +       __igt_hlist_del(n);
> > > > +       n->next = NULL;
> > > > +       n->pprev = NULL;
> > > > +}
> > > > +
> > > > +void igt_hlist_del_init(struct igt_hlist_node *n)
> > > > +{
> > > > +       if (!igt_hlist_unhashed(n)) {
> > > > +               __igt_hlist_del(n);
> > > > +               igt_hlist_init(n);
> > > > +       }
> > > > +}
> > > > +
> > > > +void igt_hlist_add_head(struct igt_hlist_node *n, struct igt_hlist_head *h)
> > > > +{
> > > > +       struct igt_hlist_node *first = h->first;
> > > > +
> > > > +       n->next = first;
> > > > +       if (first)
> > > > +               first->pprev = &n->next;
> > > > +       h->first = n;
> > > > +       n->pprev = &h->first;
> > > > +}
> > > > +
> > > > +void igt_hlist_add_before(struct igt_hlist_node *n, struct igt_hlist_node *next)
> > > > +{
> > > > +       assert(next);
> > > > +       n->pprev = next->pprev;
> > > > +       n->next = next;
> > > > +       next->pprev = &n->next;
> > > > +       *(n->pprev) = n;
> > > > +}
> > > > +
> > > > +void igt_hlist_add_behind(struct igt_hlist_node *n, struct igt_hlist_node *prev)
> > > > +{
> > > > +       n->next = prev->next;
> > > > +       prev->next = n;
> > > > +       n->pprev = &prev->next;
> > > > +
> > > > +       if (n->next)
> > > > +               n->next->pprev  = &n->next;
> > > > +}
> > > > diff --git a/lib/igt_list.h b/lib/igt_list.h
> > > > index cc93d7a0d..78e761e05 100644
> > > > --- a/lib/igt_list.h
> > > > +++ b/lib/igt_list.h
> > > > @@ -40,6 +40,10 @@
> > > >   * igt_list is a doubly-linked list where an instance of igt_list_head is a
> > > >   * head sentinel and has to be initialized.
> > > >   *
> > > > + * igt_hist is also an double linked lists, but with a single pointer list head.
> > > > + * Mostly useful for hash tables where the two pointer list head is
> > > > + * too wasteful. You lose the ability to access the tail in O(1).
> > > > + *
> > > >   * Example usage:
> > > >   *
> > > >   * |[<!-- language="C" -->
> > > > @@ -71,6 +75,13 @@ struct igt_list_head {
> > > >         struct igt_list_head *next;
> > > >  };
> > > >
> > > > +struct igt_hlist_head {
> > > > +       struct igt_hlist_node *first;
> > > > +};
> > > > +
> > > > +struct igt_hlist_node {
> > > > +       struct igt_hlist_node *next, **pprev;
> > > > +};
> > > >
> > > >  void IGT_INIT_LIST_HEAD(struct igt_list_head *head);
> > > >  void igt_list_add(struct igt_list_head *elem, struct igt_list_head *head);
> > > > @@ -81,6 +92,17 @@ void igt_list_move_tail(struct igt_list_head *elem, struct igt_list_head *list);
> > > >  int igt_list_length(const struct igt_list_head *head);
> > > >  bool igt_list_empty(const struct igt_list_head *head);
> > > >
> > > > +void igt_hlist_init(struct igt_hlist_node *h);
> > > > +int igt_hlist_unhashed(const struct igt_hlist_node *h);
> > > > +int igt_hlist_empty(const struct igt_hlist_head *h);
> > > > +void igt_hlist_del(struct igt_hlist_node *n);
> > > > +void igt_hlist_del_init(struct igt_hlist_node *n);
> > > > +void igt_hlist_add_head(struct igt_hlist_node *n, struct igt_hlist_head *h);
> > > > +void igt_hlist_add_before(struct igt_hlist_node *n,
> > > > +                         struct igt_hlist_node *next);
> > > > +void igt_hlist_add_behind(struct igt_hlist_node *n,
> > > > +                         struct igt_hlist_node *prev);
> > > > +
> > > >  #define igt_container_of(ptr, sample, member)                          \
> > > >         (__typeof__(sample))((char *)(ptr) -                            \
> > > >                                 offsetof(__typeof__(*sample), member))
> > > > @@ -96,9 +118,10 @@ bool igt_list_empty(const struct igt_list_head *head);
> > > >   * Safe against removel of the *current* list element. To achive this it
> > > >   * requires an extra helper variable `tmp` with the same type as `pos`.
> > > >   */
> > > > -#define igt_list_for_each_entry_safe(pos, tmp, head, member)                   \
> > > > +
> > > > +#define igt_list_for_each_entry_safe(pos, tmp, head, member)           \
> > > >         for (pos = igt_container_of((head)->next, pos, member),         \
> > > > -            tmp = igt_container_of((pos)->member.next, tmp, member);   \
> > > > +            tmp = igt_container_of((pos)->member.next, tmp, member);   \
> > > >              &pos->member != (head);                                    \
> > > >              pos = tmp,                                                 \
> > > >              tmp = igt_container_of((pos)->member.next, tmp, member))
> > > > @@ -108,6 +131,27 @@ bool igt_list_empty(const struct igt_list_head *head);
> > > >              &pos->member != (head);                                    \
> > > >              pos = igt_container_of((pos)->member.prev, pos, member))
> > > >
> > > > +#define igt_list_for_each_entry_safe_reverse(pos, tmp, head, member)           \
> > > > +       for (pos = igt_container_of((head)->prev, pos, member),         \
> > > > +            tmp = igt_container_of((pos)->member.prev, tmp, member);   \
> > > > +            &pos->member != (head);                                    \
> > > > +            pos = tmp,                                                 \
> > > > +            tmp = igt_container_of((pos)->member.prev, tmp, member))
> > > > +
> > > > +#define igt_hlist_entry_safe(ptr, sample, member) \
> > > > +       ({ typeof(ptr) ____ptr = (ptr); \
> > > > +          ____ptr ? igt_container_of(____ptr, sample, member) : NULL; \
> > > > +       })
> > > > +
> > > > +#define igt_hlist_for_each_entry(pos, head, member)                    \
> > > > +       for (pos = igt_hlist_entry_safe((head)->first, pos, member);    \
> > > > +            pos;                                                       \
> > > > +            pos = igt_hlist_entry_safe((pos)->member.next, pos, member))
> > > > +
> > > > +#define igt_hlist_for_each_entry_safe(pos, n, head, member)            \
> > > > +       for (pos = igt_hlist_entry_safe((head)->first, pos, member);    \
> > > > +            pos && ({ n = pos->member.next; 1; });                     \
> > > > +            pos = igt_hlist_entry_safe(n, pos, member))
> > > >
> > > >  /* IGT custom helpers */
> > > >
> > > > @@ -127,4 +171,6 @@ bool igt_list_empty(const struct igt_list_head *head);
> > > >  #define igt_list_last_entry(head, type, member) \
> > > >         igt_container_of((head)->prev, (type), member)
> > > >
> > > > +#define IGT_INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
> > > > +
> > > >  #endif /* IGT_LIST_H */
> > > > --
> > > > 2.26.0
> > > >
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

  reply	other threads:[~2021-03-17 19:13 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-17 14:45 [igt-dev] [PATCH i-g-t v26 00/35] Introduce IGT allocator Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 01/35] lib/igt_list: Add igt_list_del_init() Zbigniew Kempczyński
2021-03-17 16:40   ` Jason Ekstrand
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 02/35] lib/igt_list: igt_hlist implementation Zbigniew Kempczyński
2021-03-17 16:43   ` Jason Ekstrand
2021-03-17 17:43     ` Zbigniew Kempczyński
2021-03-17 18:02       ` Jason Ekstrand
2021-03-17 19:13         ` Zbigniew Kempczyński [this message]
2021-03-17 20:44           ` Grzegorzek, Dominik
2021-03-18 13:26             ` Grzegorzek, Dominik
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 03/35] lib/igt_map: Introduce igt_map Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 04/35] lib/igt_core: Track child process pid and tid Zbigniew Kempczyński
2021-03-18  9:07   ` Petri Latvala
2021-03-18 13:48     ` Zbigniew Kempczyński
2021-03-18 15:17       ` Petri Latvala
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 05/35] lib/intel_allocator_simple: Add simple allocator Zbigniew Kempczyński
2021-03-17 19:38   ` Jason Ekstrand
2021-03-18 10:40     ` Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 06/35] lib/intel_allocator_reloc: Add reloc allocator Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 07/35] lib/intel_allocator_random: Add random allocator Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 08/35] lib/intel_allocator: Add intel_allocator core Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 09/35] lib/intel_allocator: Try to stop smoothly instead of deinit Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 10/35] lib/intel_allocator_msgchannel: Scale to 4k of parallel clients Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 11/35] lib/intel_allocator: Separate allocator multiprocess start Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 12/35] lib/intel_bufops: Change size from 32->64 bit Zbigniew Kempczyński
2021-03-17 21:33   ` Jason Ekstrand
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 13/35] lib/intel_bufops: Add init with handle and size function Zbigniew Kempczyński
2021-03-17 21:36   ` Jason Ekstrand
2021-03-18  7:32     ` Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 14/35] lib/intel_batchbuffer: Integrate intel_bb with allocator Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 15/35] lib/intel_batchbuffer: Use relocations in intel-bb up to gen12 Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 16/35] lib/intel_batchbuffer: Create bb with strategy / vm ranges Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 17/35] lib/intel_batchbuffer: Add tracking intel_buf to intel_bb Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 18/35] lib/igt_fb: Initialize intel_buf with same size as fb Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 19/35] tests/api_intel_bb: Remove check-canonical test Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 20/35] tests/api_intel_bb: Modify test to verify intel_bb with allocator Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 21/35] tests/api_intel_bb: Add compressed->compressed copy Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 22/35] tests/api_intel_bb: Add purge-bb test Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 23/35] tests/api_intel_bb: Add simple intel-bb which uses allocator Zbigniew Kempczyński
2021-03-17 14:45 ` [igt-dev] [PATCH i-g-t v26 24/35] tests/api_intel_bb: Use allocator in delta-check test Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 25/35] tests/api_intel_bb: Check switching vm in intel-bb Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 26/35] tests/api_intel_allocator: Simple allocator test suite Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 27/35] tests/api_intel_allocator: Add execbuf with allocator example Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 28/35] tests/api_intel_allocator: Verify child can use its standalone allocator Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 29/35] tests/gem_softpin: Verify allocator and execbuf pair work together Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 30/35] tests/gem|kms: Remove intel_bb from fixture Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 31/35] tests/gem_mmap_offset: Use intel_buf wrapper code instead direct Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 32/35] tests/gem_ppgtt: Adopt test to use intel_bb with allocator Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 33/35] tests/gem_render_copy_redux: Adopt to use with intel_bb and allocator Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 34/35] tests/perf.c: Remove buffer from batch Zbigniew Kempczyński
2021-03-17 14:46 ` [igt-dev] [PATCH i-g-t v26 35/35] tests/gem_linear_blits: Use intel allocator Zbigniew Kempczyński
2021-03-17 16:03 ` [igt-dev] ✓ Fi.CI.BAT: success for Introduce IGT allocator (rev29) Patchwork
2021-03-17 17:47 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210317191315.GA123572@zkempczy-mobl2 \
    --to=zbigniew.kempczynski@intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=jason@jlekstrand.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.