[PATCH xserver 3/4] dix: Convert ResourceClientBits to a variable
Mark Kettenis
mark.kettenis at xs4all.nl
Tue May 3 15:35:06 UTC 2016
> From: Adam Jackson <ajax at redhat.com>
> Date: Tue, 3 May 2016 11:24:36 -0400
>
> This turns out to be a remarkably hot function in XID lookup. Consider
> the expansion of CLIENT_ID. We start with:
>
> #define RESOURCE_CLIENT_BITS ResourceClientBits()
> #define RESOURCE_AND_CLIENT_COUNT 29
> #define CLIENTOFFSET (RESOURCE_AND_CLIENT_COUNT - RESOURCE_CLIENT_BITS)
>
> So that's effectively:
>
> #define CLIENTOFFSET (29 - RCB())
>
> Then:
>
> #define RESOURCE_CLIENT_MASK \
> ((1 << RESOURCE_CLIENT_BITS) - 1) << CLIENTOFFSET
>
> Is effectively:
>
> #define RESOURCE_CLIENT_MASK (((1 << RCB()) - 1) << (29 - RCB())
>
> And:
>
> #define CLIENT_BITS(id) ((id) & RESOURCE_CLIENT_MASK)
> #define CLIENT_ID(id) ((int)(CLIENT_BITS(id) >> CLIENTOFFSET))
>
> Is:
>
> #define CLIENT_ID(id) \
> ((id) & (((1 << RCB()) - 1) << (29 - RCB()))) >> (29 - RCB())
>
> Since ResourceClientBits isn't marked __attribute__((pure)), the
> optimizer isn't allowed to CSE those function calls, since it doesn't
> know they don't have side effects. And, worse, ResourceClientBits
> doesn't just return an integer, it computes the ilog2 afresh every time.
>
> Instead we can just compute the value we need at argv parse.
>
> v2: Ensure ResourceClientBits is initialized even when we don't pass
> -maxclients (Alan Coopersmith)
Hmm. This is marked as _X_EXPORT, so presumably part of the driver
ABI. Exporting variables like this is generally a bad idea, at least
for ELF DSOs. Copy relocations and all that.
So isn't it better to keep this as a function call? You'd still make
it return a precalculated value instead of doing the ilog2 on each
call. Marking it as a "pure" function in addition to that should fine
too.
Cheers,
Mark
> Signed-off-by: Adam Jackson <ajax at redhat.com>
> ---
> dix/resource.c | 23 -----------------------
> include/resource.h | 4 ++--
> os/osinit.c | 1 +
> os/utils.c | 13 +++++++++++++
> 4 files changed, 16 insertions(+), 25 deletions(-)
>
> diff --git a/dix/resource.c b/dix/resource.c
> index ad71b24..f06bf58 100644
> --- a/dix/resource.c
> +++ b/dix/resource.c
> @@ -600,29 +600,6 @@ CreateNewResourceClass(void)
>
> static ClientResourceRec clientTable[MAXCLIENTS];
>
> -static unsigned int
> -ilog2(int val)
> -{
> - int bits;
> -
> - if (val <= 0)
> - return 0;
> - for (bits = 0; val != 0; bits++)
> - val >>= 1;
> - return bits - 1;
> -}
> -
> -/*****************
> - * ResourceClientBits
> - * Returns the client bit offset in the client + resources ID field
> - *****************/
> -
> -unsigned int
> -ResourceClientBits(void)
> -{
> - return (ilog2(LimitClients));
> -}
> -
> /*****************
> * InitClientResources
> * When a new client is created, call this to allocate space
> diff --git a/include/resource.h b/include/resource.h
> index 5871a4c..3cce6c6 100644
> --- a/include/resource.h
> +++ b/include/resource.h
> @@ -85,10 +85,10 @@ typedef uint32_t RESTYPE;
> #define RT_LASTPREDEF ((RESTYPE)9)
> #define RT_NONE ((RESTYPE)0)
>
> -extern _X_EXPORT unsigned int ResourceClientBits(void);
> +extern _X_EXPORT unsigned int ResourceClientBits;
> /* bits and fields within a resource id */
> #define RESOURCE_AND_CLIENT_COUNT 29 /* 29 bits for XIDs */
> -#define RESOURCE_CLIENT_BITS ResourceClientBits() /* client field offset */
> +#define RESOURCE_CLIENT_BITS ResourceClientBits /* client field offset */
> #define CLIENTOFFSET (RESOURCE_AND_CLIENT_COUNT - RESOURCE_CLIENT_BITS)
> /* resource field */
> #define RESOURCE_ID_MASK ((1 << CLIENTOFFSET) - 1)
> diff --git a/os/osinit.c b/os/osinit.c
> index 54b39a0..92aced3 100644
> --- a/os/osinit.c
> +++ b/os/osinit.c
> @@ -88,6 +88,7 @@ int limitNoFile = -1;
>
> /* The actual user defined max number of clients */
> int LimitClients = LIMITCLIENTS;
> +unsigned int ResourceClientBits;
>
> static OsSigWrapperPtr OsSigWrapper = NULL;
>
> diff --git a/os/utils.c b/os/utils.c
> index e48d9f8..8b81d39 100644
> --- a/os/utils.c
> +++ b/os/utils.c
> @@ -513,6 +513,18 @@ AdjustWaitForDelay(void *waitTime, unsigned long newdelay)
> }
> }
>
> +static unsigned int
> +ilog2(int val)
> +{
> + int bits;
> +
> + if (val <= 0)
> + return 0;
> + for (bits = 0; val != 0; bits++)
> + val >>= 1;
> + return bits - 1;
> +}
> +
> void
> UseMsg(void)
> {
> @@ -1061,6 +1073,7 @@ ProcessCommandLine(int argc, char *argv[])
> FatalError("Unrecognized option: %s\n", argv[i]);
> }
> }
> + ResourceClientBits = ilog2(LimitClients);
> }
>
> /* Implement a simple-minded font authorization scheme. The authorization
> --
> 2.7.4
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: https://lists.x.org/mailman/listinfo/xorg-devel
>
>
More information about the xorg-devel
mailing list