This improves the cache. Basically, it's kind of like four way associative
now, with LRU replacement. Also we can cache nameless entries instead of going
back to getpwuid every time.

Index: gen/pwcache.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/pwcache.c,v
retrieving revision 1.10
diff -u -p -r1.10 pwcache.c
--- gen/pwcache.c       26 Oct 2015 15:04:51 -0000      1.10
+++ gen/pwcache.c       26 Oct 2015 15:37:13 -0000
@@ -35,32 +35,52 @@
 #include <stdio.h>
 #include <string.h>
 
-#define        NCACHE  64                      /* power of 2 */
+#define        NCACHE  16                      /* power of 2 */
+#define        NLINES  4                       /* associativity */
 #define        MASK    (NCACHE - 1)            /* bits to store with */
+#define        IDX(x, i)       ((x & MASK) + i * NCACHE)
 
 char *
 user_from_uid(uid_t uid, int nouser)
 {
        static struct ncache {
                uid_t   uid;
+               short   noname;
                char    name[_PW_NAME_LEN + 1];
-       } c_uid[NCACHE];
+       } c_uid[NLINES * NCACHE];
        static char nbuf[15];           /* 32 bits == 10 digits */
        struct passwd *pw;
        struct ncache *cp;
+       unsigned int i;
 
-       cp = c_uid + (uid & MASK);
-       if (cp->uid != uid || !*cp->name) {
-               if ((pw = getpwuid(uid)) == NULL) {
-                       if (nouser)
-                               return (NULL);
-                       (void)snprintf(nbuf, sizeof(nbuf), "%u", uid);
-                       return (nbuf);
+       for (i = 0; i < NLINES; i++) {
+               cp = &c_uid[IDX(uid, i)];
+               if (!*cp->name) {
+fillit:
+                       cp->uid = uid;
+                       if ((pw = getpwuid(uid)) == NULL) {
+                               snprintf(cp->name, sizeof(cp->name), "%u", uid);
+                               cp->noname = 1;
+                       } else {
+                               strlcpy(cp->name, pw->pw_name, 
sizeof(cp->name));
+                       }
                }
-               cp->uid = uid;
-               strlcpy(cp->name, pw->pw_name, sizeof(cp->name));
+               if (cp->uid == uid) {
+                       if (nouser && cp->noname)
+                               return NULL;
+                       return cp->name;
+               }
+       }
+       /* move everybody down a slot */
+       for (i = 0; i < NLINES - 1; i++) {
+               struct ncache *next;
+
+               cp = &c_uid[IDX(uid, i)];
+               next = &c_uid[IDX(uid, i + 1)];
+               memcpy(next, cp, sizeof(*cp));
        }
-       return (cp->name);
+       cp = &c_uid[IDX(uid, 0)];
+       goto fillit;
 }
 
 char *
@@ -68,22 +88,40 @@ group_from_gid(gid_t gid, int nogroup)
 {
        static struct ncache {
                gid_t   gid;
+               short   noname;
                char    name[_PW_NAME_LEN + 1];
-       } c_gid[NCACHE];
+       } c_gid[NLINES * NCACHE];
        static char nbuf[15];           /* 32 bits == 10 digits */
        struct group *gr;
        struct ncache *cp;
+       unsigned int i;
 
-       cp = c_gid + (gid & MASK);
-       if (cp->gid != gid || !*cp->name) {
-               if ((gr = getgrgid(gid)) == NULL) {
-                       if (nogroup)
-                               return (NULL);
-                       (void)snprintf(nbuf, sizeof(nbuf), "%u", gid);
-                       return (nbuf);
+       for (i = 0; i < NLINES; i++) {
+               cp = &c_gid[IDX(gid, i)];
+               if (!*cp->name) {
+fillit:
+                       cp->gid = gid;
+                       if ((gr = getgrgid(gid)) == NULL) {
+                               snprintf(cp->name, sizeof(cp->name), "%u", gid);
+                               cp->noname = 1;
+                       } else {
+                               strlcpy(cp->name, gr->gr_name, 
sizeof(cp->name));
+                       }
                }
-               cp->gid = gid;
-               strlcpy(cp->name, gr->gr_name, sizeof(cp->name));
+               if (cp->gid == gid) {
+                       if (nogroup && cp->noname)
+                               return NULL;
+                       return cp->name;
+               }
+       }
+       /* move everybody down a slot */
+       for (i = 0; i < NLINES - 1; i++) {
+               struct ncache *next;
+
+               cp = &c_gid[IDX(gid, i)];
+               next = &c_gid[IDX(gid, i + 1)];
+               memcpy(next, cp, sizeof(*cp));
        }
-       return (cp->name);
+       cp = &c_gid[IDX(gid, 0)];
+       goto fillit;
 }

Reply via email to