Re: [PATCH 2/2] regmap: Add maple tree based register cache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Mar 25, 2023 at 07:41:02PM -0400, Liam R. Howlett wrote:

> Without use of the locking, the maple tree will generate lockdep
> complaints.

> With the mas_* family of functions, you are responsible for locking.  On
> read you can take the rcu_read_lock(), on writes you need to take
> mas_lock(&mas).

> If you have a lock you already use, you can init the tree with the
> external lock flag and set the external lock like we do in the VMA code.

Oh, that's not ideal.  regmap does have an external lock but it's
already taken outside of the cache code, the cache code shouldn't
have to worry about locking.  This does mean the maple tree locks
should never be contended, but there'll still be some overhead.
OTOH we only have to be faster than accessing the underlying bus
so it's merely annoying.  I've added the locking locally.

> > +static int regcache_maple_drop(struct regmap *map, unsigned int min,
> > +			       unsigned int max)
> > +{

> Wait, if this is for destroying the entire tree:
> 	mas_lock(&mas);
> 	mas_for_each(mas, entry, max)
> 		kfree(entry);
> 	__mt_destroy(mt);
> 	mas_unlock(&mas);

It's not just for that - it's also used for selectively
discarding some entries in the cache, we just reuse the code when
freeing the regmap.  It may be worth using the above in the map
free case, though it's not exactly a hot path.

> If it's not for the entire tree, you can free a range then write a NULL
> over the entire range.  But be conscience of the maple state range after
> the iterator ends, you will need to mas_set_range(&mas, min, max) prior
> to the mas_store_gfp().

Will writing NULL leave tree entries in place that get iterated?
Though the code will need to become more complicated anyway if we
might need to split nodes that cover more than one register.

> > +static int regcache_maple_exit(struct regmap *map)
> > +{
> > +	struct maple_tree *mt = map->cache;
> > +
> > +	/* if we've already been called then just return */
> > +	if (!mt)
> > +		return 0;

> There's not a race here with multiple tasks in here at once, right?

No, everything's locked at the caller level.  It's just
simplifying some of the error handling paths (IIRC the actual
issue is freeing a cache that was never allocated).

> > +	mt_init(mt);
> > +

> The maple tree does support bulk loading (in the b-tree sense).  You can
> put the maple tree in this state and pre-allocate nodes in bulk.
> kernel/fork.c currently does this through the vma iterator interface.
> Note that after a bulk-load, you have to ensure you call mas_destroy()
> to free any unused nodes and to potentially cause a rebalance of the
> last node (this is automatic).  But, again, like you said in your
> comment; this is good for the first pass.

Right, I saw the reallocation stuff and was going to save it for
later after I'd arranged to store ranges of registers directly in
the tree rather than having a node per register since there'll be
some overlap there.

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux