summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ufs/Makefile3
-rw-r--r--ufs/alloc.c38
-rw-r--r--ufs/dir.c8
-rw-r--r--ufs/hyper.c10
-rw-r--r--ufs/inode.c44
-rw-r--r--ufs/main.c10
-rw-r--r--ufs/pager.c105
-rw-r--r--ufs/pokeloc.c14
-rw-r--r--ufs/sizes.c47
-rw-r--r--ufs/ufs.h13
10 files changed, 170 insertions, 122 deletions
diff --git a/ufs/Makefile b/ufs/Makefile
index a1cfc4c9..b66a6259 100644
--- a/ufs/Makefile
+++ b/ufs/Makefile
@@ -24,7 +24,8 @@ SRCS = alloc.c consts.c dir.c hyper.c inode.c main.c pager.c \
sizes.c subr.c tables.c bmap.c pokeloc.c xinl.c
OBJS = $(SRCS:.c=.o)
-HURDLIBS = diskfs iohelp fshelp store pager threads ports ihash shouldbeinlibc
+HURDLIBS = diskfs iohelp fshelp store pager ports ihash shouldbeinlibc
+OTHERLIBS = -lpthread
include ../Makeconf
diff --git a/ufs/alloc.c b/ufs/alloc.c
index d8f92255..9056a8b7 100644
--- a/ufs/alloc.c
+++ b/ufs/alloc.c
@@ -64,7 +64,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
extern u_long nextgennumber;
-spin_lock_t alloclock = SPIN_LOCK_INITIALIZER;
+pthread_spinlock_t alloclock = PTHREAD_SPINLOCK_INITIALIZER;
/* Forward declarations */
static u_long ffs_hashalloc (struct node *, int, long, int,
@@ -244,7 +244,7 @@ ffs_alloc(register struct node *np,
}
assert (cred);
#endif /* DIAGNOSTIC */
- spin_lock (&alloclock);
+ pthread_spin_lock (&alloclock);
if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
goto nospace;
if (cred && !idvec_contains (cred->user->uids, 0)
@@ -263,7 +263,7 @@ ffs_alloc(register struct node *np,
bno = (daddr_t)ffs_hashalloc(np, cg, (long)bpref, size,
(u_long (*)())ffs_alloccg);
if (bno > 0) {
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
np->dn_stat.st_blocks += btodb(size);
np->dn_set_ctime = 1;
np->dn_set_mtime = 1;
@@ -278,7 +278,7 @@ ffs_alloc(register struct node *np,
(void) chkdq(ip, (long)-btodb(size), cred, FORCE);
#endif
nospace:
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
printf ("file system full");
/* ffs_fserr(fs, cred->cr_uid, "file system full"); */
/* uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); */
@@ -321,7 +321,7 @@ ffs_realloccg(register struct node *np,
panic("ffs_realloccg: missing credential\n");
#endif /* DIAGNOSTIC */
- spin_lock (&alloclock);
+ pthread_spin_lock (&alloclock);
if (!idvec_contains (cred->user->uids, 0)
&& freespace(fs, fs->fs_minfree) <= 0)
@@ -356,7 +356,7 @@ ffs_realloccg(register struct node *np,
bno = ffs_fragextend(np, cg, (long)bprev, osize, nsize);
if (bno) {
assert (bno == bprev);
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
np->dn_stat.st_blocks += btodb(nsize - osize);
np->dn_set_ctime = 1;
np->dn_set_mtime = 1;
@@ -430,7 +430,7 @@ ffs_realloccg(register struct node *np,
if (nsize < request)
ffs_blkfree(np, bno + numfrags(fs, nsize),
(long)(request - nsize));
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
np->dn_stat.st_blocks += btodb(nsize - osize);
np->dn_set_mtime = 1;
np->dn_set_ctime = 1;
@@ -457,7 +457,7 @@ nospace:
/*
* no space available
*/
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
printf ("file system full");
/* ffs_fserr(fs, cred->cr_uid, "file system full"); */
/* uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); */
@@ -660,11 +660,11 @@ diskfs_alloc_node (struct node *dir,
fs = sblock;
- spin_lock (&alloclock);
+ pthread_spin_lock (&alloclock);
if (fs->fs_cstotal.cs_nifree == 0)
{
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
goto noinodes;
}
@@ -678,7 +678,7 @@ diskfs_alloc_node (struct node *dir,
cg = ino_to_cg(fs, ipref);
ino = (ino_t)ffs_hashalloc(dir, cg, (long)ipref,
mode, ffs_nodealloccg);
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
if (ino == 0)
goto noinodes;
error = diskfs_cached_lookup (ino, &np);
@@ -694,12 +694,12 @@ diskfs_alloc_node (struct node *dir,
/*
* Set up a new generation number for this inode.
*/
- spin_lock (&gennumberlock);
+ pthread_spin_lock (&gennumberlock);
sex = diskfs_mtime->seconds;
if (++nextgennumber < (u_long)sex)
nextgennumber = sex;
np->dn_stat.st_gen = nextgennumber;
- spin_unlock (&gennumberlock);
+ pthread_spin_unlock (&gennumberlock);
*npp = np;
alloc_sync (np);
@@ -773,11 +773,11 @@ ffs_blkpref(struct node *np,
daddr_t nextblk;
fs = sblock;
- spin_lock (&alloclock);
+ pthread_spin_lock (&alloclock);
if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
if (lbn < NDADDR) {
cg = ino_to_cg(fs, np->dn->number);
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
return (fs->fs_fpg * cg + fs->fs_frag);
}
/*
@@ -796,19 +796,19 @@ ffs_blkpref(struct node *np,
for (cg = startcg; cg < fs->fs_ncg; cg++)
if (csum[cg].cs_nbfree >= avgbfree) {
fs->fs_cgrotor = cg;
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
return (fs->fs_fpg * cg + fs->fs_frag);
}
for (cg = 0; cg <= startcg; cg++)
if (csum[cg].cs_nbfree >= avgbfree) {
fs->fs_cgrotor = cg;
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
return (fs->fs_fpg * cg + fs->fs_frag);
}
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
return 0;
}
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
/*
* One or more previous blocks have been laid out. If less
* than fs_maxcontig previous blocks are contiguous, the
diff --git a/ufs/dir.c b/ufs/dir.c
index 3c5f152a..c3bd424e 100644
--- a/ufs/dir.c
+++ b/ufs/dir.c
@@ -244,9 +244,9 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type,
/* Drop what we *thought* was .. (but isn't any more) and
try *again*. */
diskfs_nput (np);
- mutex_unlock (&dp->lock);
+ pthread_mutex_unlock (&dp->lock);
err = diskfs_cached_lookup (inum, &np);
- mutex_lock (&dp->lock);
+ pthread_mutex_lock (&dp->lock);
if (err)
goto out;
retry_dotdot = inum;
@@ -259,9 +259,9 @@ diskfs_lookup_hard (struct node *dp, const char *name, enum lookup_type type,
/* Lock them in the proper order, and then
repeat the directory scan to see if this is still
right. */
- mutex_unlock (&dp->lock);
+ pthread_mutex_unlock (&dp->lock);
err = diskfs_cached_lookup (inum, &np);
- mutex_lock (&dp->lock);
+ pthread_mutex_lock (&dp->lock);
if (err)
goto out;
retry_dotdot = inum;
diff --git a/ufs/hyper.c b/ufs/hyper.c
index ece327a2..95013895 100644
--- a/ufs/hyper.c
+++ b/ufs/hyper.c
@@ -280,7 +280,7 @@ diskfs_set_hypermetadata (int wait, int clean)
{
error_t err;
- spin_lock (&alloclock);
+ pthread_spin_lock (&alloclock);
if (csum_dirty)
{
@@ -316,7 +316,7 @@ diskfs_set_hypermetadata (int wait, int clean)
if (err)
{
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
return err;
}
@@ -337,7 +337,7 @@ diskfs_set_hypermetadata (int wait, int clean)
wait = 1; /* must be synchronous */
}
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
/* Update the superblock if necessary (clean bit was just set). */
copy_sblock ();
@@ -355,7 +355,7 @@ copy_sblock ()
err = diskfs_catch_exception ();
assert_perror (err);
- spin_lock (&alloclock);
+ pthread_spin_lock (&alloclock);
if (sblock_dirty)
{
@@ -386,7 +386,7 @@ copy_sblock ()
sblock_dirty = 0;
}
- spin_unlock (&alloclock);
+ pthread_spin_unlock (&alloclock);
diskfs_end_catch_exception ();
}
diff --git a/ufs/inode.c b/ufs/inode.c
index 77a45edb..066eb1e5 100644
--- a/ufs/inode.c
+++ b/ufs/inode.c
@@ -35,7 +35,7 @@
static struct node *nodehash[INOHSZ];
static error_t read_disknode (struct node *np);
-spin_lock_t gennumberlock = SPIN_LOCK_INITIALIZER;
+pthread_spinlock_t gennumberlock = PTHREAD_SPINLOCK_INITIALIZER;
/* Initialize the inode hash table. */
void
@@ -55,15 +55,15 @@ diskfs_cached_lookup (ino_t inum, struct node **npp)
struct node *np;
error_t err;
- spin_lock (&diskfs_node_refcnt_lock);
+ pthread_spin_lock (&diskfs_node_refcnt_lock);
for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext)
{
if (np->dn->number != inum)
continue;
np->references++;
- spin_unlock (&diskfs_node_refcnt_lock);
- mutex_lock (&np->lock);
+ pthread_spin_unlock (&diskfs_node_refcnt_lock);
+ pthread_mutex_lock (&np->lock);
*npp = np;
return 0;
}
@@ -74,30 +74,32 @@ diskfs_cached_lookup (ino_t inum, struct node **npp)
dn->dirents = 0;
dn->dir_idx = 0;
- rwlock_init (&dn->allocptrlock);
+ pthread_rwlock_init (&dn->allocptrlock, NULL);
+ pthread_mutex_init (&dn->waitlock, NULL);
+ pthread_cond_init (&dn->waitcond, NULL);
dn->dirty = 0;
dn->fileinfo = 0;
np = diskfs_make_node (dn);
np->cache_id = inum;
- mutex_lock (&np->lock);
+ pthread_mutex_lock (&np->lock);
dn->hnext = nodehash[INOHASH(inum)];
if (dn->hnext)
dn->hnext->dn->hprevp = &dn->hnext;
dn->hprevp = &nodehash[INOHASH(inum)];
nodehash[INOHASH(inum)] = np;
- spin_unlock (&diskfs_node_refcnt_lock);
+ pthread_spin_unlock (&diskfs_node_refcnt_lock);
err = read_disknode (np);
if (!diskfs_check_readonly () && !np->dn_stat.st_gen)
{
- spin_lock (&gennumberlock);
+ pthread_spin_lock (&gennumberlock);
if (++nextgennumber < diskfs_mtime->seconds)
nextgennumber = diskfs_mtime->seconds;
np->dn_stat.st_gen = nextgennumber;
- spin_unlock (&gennumberlock);
+ pthread_spin_unlock (&gennumberlock);
np->dn_set_ctime = 1;
}
@@ -117,14 +119,14 @@ ifind (ino_t inum)
{
struct node *np;
- spin_lock (&diskfs_node_refcnt_lock);
+ pthread_spin_lock (&diskfs_node_refcnt_lock);
for (np = nodehash[INOHASH(inum)]; np; np = np->dn->hnext)
{
if (np->dn->number != inum)
continue;
assert (np->references);
- spin_unlock (&diskfs_node_refcnt_lock);
+ pthread_spin_unlock (&diskfs_node_refcnt_lock);
return np;
}
assert (0);
@@ -168,7 +170,7 @@ diskfs_lost_hardrefs (struct node *np)
if (np->dn->fileinfo)
{
- spin_lock (&_libports_portrefcntlock);
+ pthread_spin_lock (&_libports_portrefcntlock);
pi = (struct port_info *) np->dn->fileinfo->p;
if (pi->refcnt == 1)
{
@@ -178,7 +180,7 @@ diskfs_lost_hardrefs (struct node *np)
can't happen as long as we hold NP locked. So
we can safely unlock _libports_portrefcntlock for
the following call. */
- spin_unlock (&_libports_portrefcntlock);
+ pthread_spin_unlock (&_libports_portrefcntlock);
/* Right now the node is locked with no hard refs;
this is an anomalous situation. Before messing with
@@ -197,7 +199,7 @@ diskfs_lost_hardrefs (struct node *np)
diskfs_nput (np);
}
else
- spin_unlock (&_libports_portrefcntlock);
+ pthread_spin_unlock (&_libports_portrefcntlock);
}
#endif
}
@@ -440,7 +442,7 @@ diskfs_node_iterate (error_t (*fun)(struct node *))
/* Acquire a reference on all the nodes in the hash table
and enter them into a list on the stack. */
- spin_lock (&diskfs_node_refcnt_lock);
+ pthread_spin_lock (&diskfs_node_refcnt_lock);
for (n = 0; n < INOHSZ; n++)
for (np = nodehash[n]; np; np = np->dn->hnext)
{
@@ -450,16 +452,16 @@ diskfs_node_iterate (error_t (*fun)(struct node *))
i->np = np;
list = i;
}
- spin_unlock (&diskfs_node_refcnt_lock);
+ pthread_spin_unlock (&diskfs_node_refcnt_lock);
err = 0;
for (i = list; i; i = i->next)
{
if (!err)
{
- mutex_lock (&i->np->lock);
+ pthread_mutex_lock (&i->np->lock);
err = (*fun)(i->np);
- mutex_unlock (&i->np->lock);
+ pthread_mutex_unlock (&i->np->lock);
}
diskfs_nrele (i->np);
}
@@ -646,14 +648,14 @@ diskfs_S_file_get_storage_info (struct protid *cred,
return EOPNOTSUPP;
np = cred->po->np;
- mutex_lock (&np->lock);
+ pthread_mutex_lock (&np->lock);
/* See if this file fits in the direct block pointers. If not, punt
for now. (Reading indir blocks is a pain, and I'm postponing
pain.) XXX */
if (np->allocsize > NDADDR * sblock->fs_bsize)
{
- mutex_unlock (&np->lock);
+ pthread_mutex_unlock (&np->lock);
return EINVAL;
}
@@ -685,7 +687,7 @@ diskfs_S_file_get_storage_info (struct protid *cred,
}
diskfs_end_catch_exception ();
- mutex_unlock (&np->lock);
+ pthread_mutex_unlock (&np->lock);
if (! err)
err = store_clone (store, &file_store);
diff --git a/ufs/main.c b/ufs/main.c
index 242107f4..9fc21f81 100644
--- a/ufs/main.c
+++ b/ufs/main.c
@@ -46,19 +46,19 @@ warp_root (void)
error_t err;
err = diskfs_cached_lookup (2, &diskfs_root_node);
assert (!err);
- mutex_unlock (&diskfs_root_node->lock);
+ pthread_mutex_unlock (&diskfs_root_node->lock);
}
/* XXX */
-struct mutex printf_lock = MUTEX_INITIALIZER;
+pthread_mutex_t printf_lock = PTHREAD_MUTEX_INITIALIZER;
int printf (const char *fmt, ...)
{
va_list arg;
int done;
va_start (arg, fmt);
- mutex_lock (&printf_lock);
+ pthread_mutex_lock (&printf_lock);
done = vprintf (fmt, arg);
- mutex_unlock (&printf_lock);
+ pthread_mutex_unlock (&printf_lock);
va_end (arg);
return done;
}
@@ -195,7 +195,7 @@ main (int argc, char **argv)
/* SET HOST NAME */
/* And this thread is done with its work. */
- cthread_exit (0);
+ pthread_exit (NULL);
return 0;
}
diff --git a/ufs/pager.c b/ufs/pager.c
index 3038932d..1e3d140c 100644
--- a/ufs/pager.c
+++ b/ufs/pager.c
@@ -21,9 +21,9 @@
#include <unistd.h>
#include <hurd/store.h>
-spin_lock_t node2pagelock = SPIN_LOCK_INITIALIZER;
+pthread_spinlock_t node2pagelock = PTHREAD_SPINLOCK_INITIALIZER;
-spin_lock_t unlocked_pagein_lock = SPIN_LOCK_INITIALIZER;
+pthread_spinlock_t unlocked_pagein_lock = PTHREAD_SPINLOCK_INITIALIZER;
#ifdef DONT_CACHE_MEMORY_OBJECTS
#define MAY_CACHE 0
@@ -47,11 +47,11 @@ find_address (struct user_pager_info *upi,
vm_address_t offset,
daddr_t *addr,
int *disksize,
- struct rwlock **nplock,
+ pthread_rwlock_t **nplock,
int isread)
{
error_t err;
- struct rwlock *lock;
+ pthread_rwlock_t *lock;
assert (upi->type == DISK || upi->type == FILE_DATA);
@@ -81,37 +81,49 @@ find_address (struct user_pager_info *upi,
I think this is sufficiently rare to put it off for the time
being.) */
- spin_lock (&unlocked_pagein_lock);
+ pthread_spin_lock (&unlocked_pagein_lock);
if (offset >= upi->allow_unlocked_pagein
&& (offset + vm_page_size
<= upi->allow_unlocked_pagein + upi->unlocked_pagein_length))
{
- spin_unlock (&unlocked_pagein_lock);
+ pthread_spin_unlock (&unlocked_pagein_lock);
*nplock = 0;
goto have_lock;
}
- spin_unlock (&unlocked_pagein_lock);
+ pthread_spin_unlock (&unlocked_pagein_lock);
/* Block on the rwlock if necessary; but when we wake up,
don't acquire it; check again from the top.
This is mutated inline from rwlock.h. */
lock = &np->dn->allocptrlock;
- mutex_lock (&lock->master);
- if (lock->readers == -1 || lock->writers_waiting)
+ /*
+ TD - Why do we lock first?
+ To prevent this nigh-impossible scenario:
+ 1) trylock - writer has lock
+ 2) switch back to writer before we lock waitlock
+ 3) writer finishes: releases lock and broadcasts
+ 4) we wait for a condition that will never get broadcast
+ With this, either we get the lock, or we get the signal.
+ */
+ pthread_mutex_lock (&np->dn->waitlock);
+ if (pthread_rwlock_tryrdlock (lock))
{
- lock->readers_waiting++;
- condition_wait (&lock->wakeup, &lock->master);
- lock->readers_waiting--;
- mutex_unlock (&lock->master);
+ /*
+ TD - we now don't block on the rwlock. Instead, we wait on a
+ condition that will be signalled when the lock is unlocked,
+ or when it is safe not to lock the page. We don't spin on an
+ invariant, as spurius wakeups can do no harm.
+ */
+ pthread_cond_wait (&np->dn->waitcond, &np->dn->waitlock);
+ pthread_mutex_unlock (&np->dn->waitlock);
goto try_again;
}
- lock->readers++;
- mutex_unlock (&lock->master);
+ pthread_mutex_unlock (&np->dn->waitlock);
*nplock = lock;
}
else
{
- rwlock_reader_lock (&np->dn->allocptrlock);
+ pthread_rwlock_rdlock (&np->dn->allocptrlock);
*nplock = &np->dn->allocptrlock;
}
@@ -120,7 +132,7 @@ find_address (struct user_pager_info *upi,
if (offset >= np->allocsize)
{
if (*nplock)
- rwlock_reader_unlock (*nplock);
+ pthread_rwlock_unlock (*nplock);
if (isread)
return EIO;
else
@@ -138,7 +150,7 @@ find_address (struct user_pager_info *upi,
err = fetch_indir_spec (np, lblkno (sblock, offset), indirs);
if (err && *nplock)
- rwlock_reader_unlock (*nplock);
+ pthread_rwlock_unlock (*nplock);
else
{
if (indirs[0].bno)
@@ -162,7 +174,7 @@ pager_read_page (struct user_pager_info *pager,
int *writelock)
{
error_t err;
- struct rwlock *nplock;
+ pthread_rwlock_t *nplock;
daddr_t addr;
int disksize;
@@ -193,7 +205,7 @@ pager_read_page (struct user_pager_info *pager,
}
if (nplock)
- rwlock_reader_unlock (nplock);
+ pthread_rwlock_unlock (nplock);
return err;
}
@@ -207,7 +219,7 @@ pager_write_page (struct user_pager_info *pager,
{
daddr_t addr;
int disksize;
- struct rwlock *nplock;
+ pthread_rwlock_t *nplock;
error_t err;
err = find_address (pager, page, &addr, &disksize, &nplock, 0);
@@ -226,7 +238,7 @@ pager_write_page (struct user_pager_info *pager,
err = 0;
if (nplock)
- rwlock_reader_unlock (nplock);
+ pthread_rwlock_unlock (nplock);
return err;
}
@@ -268,7 +280,7 @@ pager_unlock_page (struct user_pager_info *pager,
dn = np->dn;
di = dino (dn->number);
- rwlock_writer_lock (&dn->allocptrlock);
+ pthread_rwlock_wrlock (&dn->allocptrlock);
/* If this is the last block, we don't let it get unlocked. */
if (address + __vm_page_size
@@ -276,21 +288,31 @@ pager_unlock_page (struct user_pager_info *pager,
{
printf ("attempt to unlock at last block denied\n");
fflush (stdout);
- rwlock_writer_unlock (&dn->allocptrlock);
+ pthread_rwlock_unlock (&dn->allocptrlock);
+ /* Wake up any remaining sleeping readers. Wow, so much work.... */
+ pthread_mutex_lock (&dn->waitlock);
+ pthread_cond_broadcast (&dn->waitcond);
+ pthread_mutex_unlock (&dn->waitlock);
return EIO;
}
err = fetch_indir_spec (np, lblkno (sblock, address), indirs);
if (err)
{
- rwlock_writer_unlock (&dn->allocptrlock);
+ pthread_rwlock_unlock (&dn->allocptrlock);
+ pthread_mutex_lock (&dn->waitlock);
+ pthread_cond_broadcast (&dn->waitcond);
+ pthread_mutex_unlock (&dn->waitlock);
return EIO;
}
err = diskfs_catch_exception ();
if (err)
{
- rwlock_writer_unlock (&dn->allocptrlock);
+ pthread_rwlock_unlock (&dn->allocptrlock);
+ pthread_mutex_lock (&dn->waitlock);
+ pthread_cond_broadcast (&dn->waitcond);
+ pthread_mutex_unlock (&dn->waitlock);
return EIO;
}
@@ -421,7 +443,10 @@ pager_unlock_page (struct user_pager_info *pager,
out:
diskfs_end_catch_exception ();
- rwlock_writer_unlock (&dn->allocptrlock);
+ pthread_rwlock_unlock (&dn->allocptrlock);
+ pthread_mutex_lock (&dn->waitlock);
+ pthread_cond_broadcast (&dn->waitcond);
+ pthread_mutex_unlock (&dn->waitlock);
return err;
}
@@ -452,10 +477,10 @@ pager_clear_user_data (struct user_pager_info *upi)
/* XXX Do the right thing for the disk pager here too. */
if (upi->type == FILE_DATA)
{
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
if (upi->np->dn->fileinfo == upi)
upi->np->dn->fileinfo = 0;
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
diskfs_nrele_light (upi->np);
}
free (upi);
@@ -491,11 +516,11 @@ diskfs_file_update (struct node *np,
struct dirty_indir *d, *tmp;
struct user_pager_info *upi;
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
upi = np->dn->fileinfo;
if (upi)
ports_port_ref (upi->p);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
if (upi)
{
@@ -522,11 +547,11 @@ flush_node_pager (struct node *node)
struct disknode *dn = node->dn;
struct dirty_indir *dirty = dn->dirty;
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
upi = dn->fileinfo;
if (upi)
ports_port_ref (upi->p);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
if (upi)
{
@@ -558,7 +583,7 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
&& (!direct_symlink_extension
|| np->dn_stat.st_size >= sblock->fs_maxsymlinklen)));
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
do
if (!np->dn->fileinfo)
{
@@ -575,7 +600,7 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
{
diskfs_nrele_light (np);
free (upi);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
return MACH_PORT_NULL;
}
np->dn->fileinfo = upi;
@@ -596,7 +621,7 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
}
while (right == MACH_PORT_NULL);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
mach_port_insert_right (mach_task_self (), right, right,
MACH_MSG_TYPE_MAKE_SEND);
@@ -611,11 +636,11 @@ drop_pager_softrefs (struct node *np)
{
struct user_pager_info *upi;
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
upi = np->dn->fileinfo;
if (upi)
ports_port_ref (upi->p);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
if (MAY_CACHE && upi)
pager_change_attributes (upi->p, 0, MEMORY_OBJECT_COPY_DELAY, 0);
@@ -630,11 +655,11 @@ allow_pager_softrefs (struct node *np)
{
struct user_pager_info *upi;
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
upi = np->dn->fileinfo;
if (upi)
ports_port_ref (upi->p);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
if (MAY_CACHE && upi)
pager_change_attributes (upi->p, 1, MEMORY_OBJECT_COPY_DELAY, 0);
diff --git a/ufs/pokeloc.c b/ufs/pokeloc.c
index 267aa106..e1d5ffcb 100644
--- a/ufs/pokeloc.c
+++ b/ufs/pokeloc.c
@@ -28,7 +28,7 @@ struct pokeloc
};
struct pokeloc *pokelist;
-spin_lock_t pokelistlock = SPIN_LOCK_INITIALIZER;
+pthread_spinlock_t pokelistlock = PTHREAD_SPINLOCK_INITIALIZER;
/* Remember that data here on the disk has been modified. */
void
@@ -41,10 +41,10 @@ record_poke (void *loc, vm_size_t length)
pl->offset = trunc_page (offset);
pl->length = round_page (offset + length) - pl->offset;
- spin_lock (&pokelistlock);
+ pthread_spin_lock (&pokelistlock);
pl->next = pokelist;
pokelist = pl;
- spin_unlock (&pokelistlock);
+ pthread_spin_unlock (&pokelistlock);
}
/* Get rid of any outstanding pokes. */
@@ -53,10 +53,10 @@ flush_pokes ()
{
struct pokeloc *pl;
- spin_lock (&pokelistlock);
+ pthread_spin_lock (&pokelistlock);
pl = pokelist;
pokelist = 0;
- spin_unlock (&pokelistlock);
+ pthread_spin_unlock (&pokelistlock);
while (pl)
{
@@ -72,7 +72,7 @@ sync_disk (int wait)
{
struct pokeloc *pl, *tmp;
- spin_lock (&pokelistlock);
+ pthread_spin_lock (&pokelistlock);
for (pl = pokelist; pl; pl = tmp)
{
pager_sync_some (diskfs_disk_pager, pl->offset, pl->length, wait);
@@ -80,6 +80,6 @@ sync_disk (int wait)
free (pl);
}
pokelist = 0;
- spin_unlock (&pokelistlock);
+ pthread_spin_unlock (&pokelistlock);
}
diff --git a/ufs/sizes.c b/ufs/sizes.c
index 58cbfc98..e3d51b7d 100644
--- a/ufs/sizes.c
+++ b/ufs/sizes.c
@@ -91,11 +91,11 @@ diskfs_truncate (struct node *np,
immediately. (We are implicitly changing the data to zeros
and doing it without the kernel's immediate knowledge;
accordingl we must help out the kernel thusly.) */
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
upi = np->dn->fileinfo;
if (upi)
ports_port_ref (upi->p);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
if (upi)
{
@@ -115,7 +115,7 @@ diskfs_truncate (struct node *np,
ports_port_deref (upi->p);
}
- rwlock_writer_lock (&np->dn->allocptrlock);
+ pthread_rwlock_wrlock (&np->dn->allocptrlock);
/* Update the size on disk; fsck will finish freeing blocks if necessary
should we crash. */
@@ -250,7 +250,13 @@ diskfs_truncate (struct node *np,
np->dn_set_ctime = 1;
diskfs_node_update (np, 1);
- rwlock_writer_unlock (&np->dn->allocptrlock);
+ pthread_rwlock_unlock (&np->dn->allocptrlock);
+ /* Wake up any remaining sleeping readers.
+ This sequence of three calls is now necessary whenever we acquire a write
+ lock on allocptrlock. If we do not, we may leak some readers. */
+ pthread_mutex_lock (&np->dn->waitlock);
+ pthread_cond_broadcast (&np->dn->waitcond);
+ pthread_mutex_unlock (&np->dn->waitlock);
/* At this point the last block (as defined by np->allocsize)
might not be allocated. We need to allocate it to maintain
@@ -275,11 +281,11 @@ diskfs_truncate (struct node *np,
diskfs_end_catch_exception ();
/* Now we can permit delayed copies again. */
- spin_lock (&node2pagelock);
+ pthread_spin_lock (&node2pagelock);
upi = np->dn->fileinfo;
if (upi)
ports_port_ref (upi->p);
- spin_unlock (&node2pagelock);
+ pthread_spin_unlock (&node2pagelock);
if (upi)
{
pager_change_attributes (upi->p, MAY_CACHE,
@@ -415,15 +421,23 @@ block_extended (struct node *np,
assert_perror (err);
/* Allow these pageins to occur even though we're holding the lock */
- spin_lock (&unlocked_pagein_lock);
+ pthread_spin_lock (&unlocked_pagein_lock);
np->dn->fileinfo->allow_unlocked_pagein = lbn * sblock->fs_bsize;
np->dn->fileinfo->unlocked_pagein_length = round_page (old_size);
- spin_unlock (&unlocked_pagein_lock);
+ pthread_spin_unlock (&unlocked_pagein_lock);
/* Make sure all waiting pageins see this change. */
- mutex_lock (&np->dn->allocptrlock.master);
- condition_broadcast (&np->dn->allocptrlock.wakeup);
- mutex_unlock (&np->dn->allocptrlock.master);
+ /* BDD - Is this sane? */
+ /* TD - No... no it wasn't. But, it looked right. */
+ /*
+ This new code should, SHOULD, behave as the original code did.
+ This will wake up all readers waiting on the lock. This code favors
+ strongly writers, but, as of making this change, pthreads favors
+ writers, and cthreads did favor writers.
+ */
+ pthread_mutex_lock (&np->dn->waitlock);
+ pthread_cond_broadcast (&np->dn->waitcond);
+ pthread_mutex_unlock (&np->dn->waitlock);
/* Force the pages in core and make sure they are dirty */
for (pokeaddr = (int *)mapaddr;
@@ -432,10 +446,10 @@ block_extended (struct node *np,
*pokeaddr = *pokeaddr;
/* Turn off the special pagein permission */
- spin_lock (&unlocked_pagein_lock);
+ pthread_spin_lock (&unlocked_pagein_lock);
np->dn->fileinfo->allow_unlocked_pagein = 0;
np->dn->fileinfo->unlocked_pagein_length = 0;
- spin_unlock (&unlocked_pagein_lock);
+ pthread_spin_unlock (&unlocked_pagein_lock);
/* Undo mapping */
mach_port_deallocate (mach_task_self (), mapobj);
@@ -497,7 +511,7 @@ diskfs_grow (struct node *np,
if (size == 0)
size = sblock->fs_bsize;
- rwlock_writer_lock (&np->dn->allocptrlock);
+ pthread_rwlock_wrlock (&np->dn->allocptrlock);
/* The old last block of the file. */
olbn = lblkno (sblock, np->allocsize - 1);
@@ -680,7 +694,10 @@ diskfs_grow (struct node *np,
np->allocsize = newallocsize;
}
- rwlock_writer_unlock (&np->dn->allocptrlock);
+ pthread_rwlock_unlock (&np->dn->allocptrlock);
+ pthread_mutex_lock (&np->dn->waitlock);
+ pthread_cond_broadcast (&np->dn->waitcond);
+ pthread_mutex_unlock (&np->dn->waitlock);
if (need_sync)
diskfs_file_update (np, 1);
diff --git a/ufs/ufs.h b/ufs/ufs.h
index f59784d5..0a79f560 100644
--- a/ufs/ufs.h
+++ b/ufs/ufs.h
@@ -25,6 +25,7 @@
#include <hurd/diskfs.h>
#include <sys/mman.h>
#include <assert.h>
+#include <pthread.h>
#include <features.h>
#include "fs.h"
#include "dinode.h"
@@ -54,7 +55,9 @@ struct disknode
/* Links on hash list. */
struct node *hnext, **hprevp;
- struct rwlock allocptrlock;
+ pthread_rwlock_t allocptrlock;
+ pthread_mutex_t waitlock;
+ pthread_cond_t waitcond;
struct dirty_indir *dirty;
@@ -112,14 +115,14 @@ extern struct csum *csum;
int sblock_dirty;
int csum_dirty;
-spin_lock_t node2pagelock;
+pthread_spinlock_t node2pagelock;
-spin_lock_t alloclock;
+pthread_spinlock_t alloclock;
-spin_lock_t gennumberlock;
+pthread_spinlock_t gennumberlock;
u_long nextgennumber;
-spin_lock_t unlocked_pagein_lock;
+pthread_spinlock_t unlocked_pagein_lock;
/* The compat_mode specifies whether or not we write
extensions onto the disk. */