From owner-freebsd-current Mon Dec 4 13:11:17 2000 From owner-freebsd-current@FreeBSD.ORG Mon Dec 4 13:11:09 2000 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from net2.gendyn.com (nat2.gendyn.com [204.60.171.12]) by hub.freebsd.org (Postfix) with ESMTP id 42EDA37B400 for ; Mon, 4 Dec 2000 13:11:09 -0800 (PST) Received: from [153.11.11.3] (helo=plunger.gdeb.com) by net2.gendyn.com with esmtp (Exim 2.12 #1) id 1432su-000Au2-00 for current@freebsd.org; Mon, 4 Dec 2000 16:10:52 -0500 Received: from orion.caen.gdeb.com ([153.11.109.11]) by plunger.gdeb.com with ESMTP id QAA19730 for ; Mon, 4 Dec 2000 16:07:00 -0500 (EST) Received: from vigrid.com (gpz.clc.gdeb.com [192.168.3.12]) by orion.caen.gdeb.com (8.9.3/8.9.3) with ESMTP id QAA12644 for ; Mon, 4 Dec 2000 16:07:15 -0500 (EST) (envelope-from eischen@vigrid.com) Sender: eghk@gdeb.com Message-ID: <3A2C088B.B9D23B7@vigrid.com> Date: Mon, 04 Dec 2000 16:11:39 -0500 From: Dan Eischen X-Mailer: Mozilla 4.75 [en] (X11; U; SunOS 5.8 sun4u) X-Accept-Language: en MIME-Version: 1.0 To: current@freebsd.org Subject: Making {open,close,read,tell,seek}dir thread-safe. Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG I started a cleanup of libc to make it thread-safe. I would like to get rid of the hash table in libc/gen/telldir.c and maintain telldir position information on a per-DIR basis. A summary of the changes are as follows: o Add a LIST_HEAD to DIR to contain a queue of telldir positions. Also add a location count (used as the magic for telldir) to DIR. A future change may also add a mutex/lock. o Remove the hash table from telldir.c. Recode to use queue macros. o Remove 'const' from 'telldir(const DIR *)'. o Remove 'register' variables as suggested in another recent thread. Question: Is there a reason to use a hash table in each DIR instead of a list (for performance reasons)? Proposed diffs below. -- Dan Eischen Index: dirent.h =================================================================== RCS file: /opt/FreeBSD/cvs/src/include/dirent.h,v retrieving revision 1.7 diff -u -r1.7 dirent.h --- dirent.h 1999/12/29 05:01:20 1.7 +++ dirent.h 2000/12/04 20:03:49 @@ -46,12 +46,15 @@ #ifdef _POSIX_SOURCE typedef void * DIR; #else +#include #define d_ino d_fileno /* backward compatibility */ /* definitions for library routines operating on directories. */ #define DIRBLKSIZ 1024 +struct ddloc; + /* structure describing an open directory. */ typedef struct _dirdesc { int dd_fd; /* file descriptor associated with directory */ @@ -61,7 +64,9 @@ int dd_len; /* size of data buffer */ long dd_seek; /* magic cookie returned by getdirentries */ long dd_rewind; /* magic cookie for rewinding */ - int dd_flags; /* flags for readdir */ + int dd_flags; /* flags for readdir */\ + long dd_loccnt; /* current key for dd_locq entry */ + LIST_HEAD(, ddloc) dd_locq; /* telldir position recording */ } DIR; #define dirfd(dirp) ((dirp)->dd_fd) @@ -89,7 +94,7 @@ int closedir __P((DIR *)); #ifndef _POSIX_SOURCE DIR *__opendir2 __P((const char *, int)); -long telldir __P((const DIR *)); +long telldir __P((DIR *)); void seekdir __P((DIR *, long)); int scandir __P((const char *, struct dirent ***, int (*)(struct dirent *), int (*)(const void *, const void *))); Index: libc/gen/closedir.c =================================================================== RCS file: /opt/FreeBSD/cvs/src/lib/libc/gen/closedir.c,v retrieving revision 1.6 diff -u -r1.6 closedir.c --- libc/gen/closedir.c 2000/01/27 23:06:14 1.6 +++ libc/gen/closedir.c 2000/12/04 20:03:30 @@ -58,7 +58,7 @@ dirp->dd_fd = -1; dirp->dd_loc = 0; free((void *)dirp->dd_buf); - free((void *)dirp); _reclaim_telldir(dirp); + free((void *)dirp); return(_close(fd)); } Index: libc/gen/opendir.c =================================================================== RCS file: /opt/FreeBSD/cvs/src/lib/libc/gen/opendir.c,v retrieving revision 1.10 diff -u -r1.10 opendir.c --- libc/gen/opendir.c 2000/01/27 23:06:18 1.10 +++ libc/gen/opendir.c 2000/12/04 20:03:13 @@ -259,6 +259,8 @@ dirp->dd_loc = 0; dirp->dd_fd = fd; dirp->dd_flags = flags; + dirp->dd_loccnt = 0; + LIST_INIT(&dirp->dd_locq); /* * Set up seek point for rewinddir. Index: libc/gen/telldir.c =================================================================== RCS file: /opt/FreeBSD/cvs/src/lib/libc/gen/telldir.c,v retrieving revision 1.4 diff -u -r1.4 telldir.c --- libc/gen/telldir.c 1995/05/30 05:40:26 1.4 +++ libc/gen/telldir.c 2000/12/04 20:18:22 @@ -54,39 +54,28 @@ * associated with that return value. */ struct ddloc { - struct ddloc *loc_next;/* next structure in list */ + LIST_ENTRY(ddloc) loc_lqe; /* list entry */ long loc_index; /* key associated with structure */ long loc_seek; /* magic cookie returned by getdirentries */ long loc_loc; /* offset of entry in buffer */ - const DIR* loc_dirp; /* directory which used this entry */ }; -#define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */ -#define LOCHASH(i) ((i)&(NDIRHASH-1)) - -static long dd_loccnt; /* Index of entry for sequential readdir's */ -static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */ - /* * return a pointer into a directory */ long telldir(dirp) - const DIR *dirp; + DIR *dirp; { - register int index; - register struct ddloc *lp; + struct ddloc *lp; if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) return (-1); - index = dd_loccnt++; - lp->loc_index = index; + lp->loc_index = dirp->dd_loccnt++; lp->loc_seek = dirp->dd_seek; lp->loc_loc = dirp->dd_loc; - lp->loc_dirp = dirp; - lp->loc_next = dd_hash[LOCHASH(index)]; - dd_hash[LOCHASH(index)] = lp; - return (index); + LIST_INSERT_HEAD(&dirp->dd_locq, lp, loc_lqe); + return (lp->loc_index); } /* @@ -95,20 +84,15 @@ */ void _seekdir(dirp, loc) - register DIR *dirp; + DIR *dirp; long loc; { - register struct ddloc *lp; - register struct ddloc **prevlp; + struct ddloc *lp; struct dirent *dp; - prevlp = &dd_hash[LOCHASH(loc)]; - lp = *prevlp; - while (lp != NULL) { + LIST_FOREACH(lp, &dirp->dd_locq, loc_lqe) { if (lp->loc_index == loc) break; - prevlp = &lp->loc_next; - lp = lp->loc_next; } if (lp == NULL) return; @@ -124,7 +108,7 @@ } found: #ifdef SINGLEUSE - *prevlp = lp->loc_next; + LIST_REMOVE(lp, loc_lqe); free((caddr_t)lp); #endif } @@ -134,24 +118,16 @@ */ void _reclaim_telldir(dirp) - register const DIR *dirp; + DIR *dirp; { - register struct ddloc *lp; - register struct ddloc **prevlp; - int i; - - for (i = 0; i < NDIRHASH; i++) { - prevlp = &dd_hash[i]; - lp = *prevlp; - while (lp != NULL) { - if (lp->loc_dirp == dirp) { - *prevlp = lp->loc_next; - free((caddr_t)lp); - lp = *prevlp; - continue; - } - prevlp = &lp->loc_next; - lp = lp->loc_next; - } + struct ddloc *lp; + struct ddloc *templp; + + lp = LIST_FIRST(&dirp->dd_locq); + while (lp != NULL) { + templp = lp; + lp = LIST_NEXT(lp, loc_lqe); + free(templp); } + LIST_INIT(&dirp->dd_locq); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message