diff -durN -X dontdiff linux/Makefile linux-2.4.18preempt-mutex-pi2/Makefile --- linux/Makefile Fri Oct 25 00:09:03 2002 +++ linux-2.4.18preempt-mutex-pi2/Makefile Sat Nov 2 20:31:03 2002 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 18 -EXTRAVERSION = +EXTRAVERSION = preempt-mutex-pi2 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -durN -X dontdiff linux/arch/i386/config.in linux-2.4.18preempt-mutex-pi2/arch/i386/config.in --- linux/arch/i386/config.in Thu Sep 19 17:09:16 2002 +++ linux-2.4.18preempt-mutex-pi2/arch/i386/config.in Sat Nov 2 00:07:19 2002 @@ -186,6 +186,12 @@ bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR bool 'Symmetric multi-processing support' CONFIG_SMP bool 'Preemptible Kernel' CONFIG_PREEMPT +if [ "$CONFIG_PREEMPT" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'dcache mutex' CONFIG_DCACHE_MTX +fi +if [ "$CONFIG_PREEMPT" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'mutex priority inheritance' CONFIG_MTX_PI +fi if [ "$CONFIG_SMP" != "y" ]; then bool 'Local APIC support on uniprocessors' CONFIG_X86_UP_APIC dep_bool 'IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC $CONFIG_X86_UP_APIC diff -durN -X dontdiff linux/arch/i386/lib/dec_and_lock.c linux-2.4.18preempt-mutex-pi2/arch/i386/lib/dec_and_lock.c --- linux/arch/i386/lib/dec_and_lock.c Thu Sep 19 17:09:16 2002 +++ linux-2.4.18preempt-mutex-pi2/arch/i386/lib/dec_and_lock.c Sat Nov 2 00:07:18 2002 @@ -10,6 +10,7 @@ #include #include #include +#include int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) { @@ -39,3 +40,14 @@ spin_unlock(lock); return 0; } + +#ifdef CONFIG_PREEMPT +int atomic_dec_and_mutex_lock(atomic_t *atomic, p_mutex_t *mtx) +{ + p_mutex_down(mtx); + if (atomic_dec_and_test(atomic)) + return 1; + p_mutex_up(mtx); + return 0; +} +#endif diff -durN -X dontdiff linux/drivers/hotplug/pci_hotplug_core.c linux-2.4.18preempt-mutex-pi2/drivers/hotplug/pci_hotplug_core.c --- linux/drivers/hotplug/pci_hotplug_core.c Thu Sep 19 17:07:20 2002 +++ linux-2.4.18preempt-mutex-pi2/drivers/hotplug/pci_hotplug_core.c Sat Nov 2 00:08:10 2002 @@ -176,17 +176,17 @@ { struct list_head *list; - spin_lock(&dcache_lock); + lock_dcache(); list_for_each(list, &dentry->d_subdirs) { struct dentry *de = list_entry(list, struct dentry, d_child); if (pcihpfs_positive(de)) { - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } } - spin_unlock(&dcache_lock); + unlock_dcache(); return 1; } diff -durN -X dontdiff linux/fs/affs/amigaffs.c linux-2.4.18preempt-mutex-pi2/fs/affs/amigaffs.c --- linux/fs/affs/amigaffs.c Thu Sep 19 17:06:32 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/affs/amigaffs.c Sat Nov 2 00:07:07 2002 @@ -134,7 +134,7 @@ void *data = dentry->d_fsdata; struct list_head *head, *next; - spin_lock(&dcache_lock); + lock_dcache(); head = &inode->i_dentry; next = head->next; while (next != head) { @@ -145,7 +145,7 @@ } next = next->next; } - spin_unlock(&dcache_lock); + unlock_dcache(); } diff -durN -X dontdiff linux/fs/autofs4/expire.c linux-2.4.18preempt-mutex-pi2/fs/autofs4/expire.c --- linux/fs/autofs4/expire.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/autofs4/expire.c Sat Nov 2 00:07:11 2002 @@ -164,7 +164,7 @@ timeout = sbi->exp_timeout; - spin_lock(&dcache_lock); + lock_dcache(); for(tmp = root->d_subdirs.next; tmp != &root->d_subdirs; tmp = tmp->next) { @@ -203,12 +203,12 @@ list_del(&root->d_subdirs); list_add(&root->d_subdirs, &dentry->d_child); dget(dentry); - spin_unlock(&dcache_lock); + unlock_dcache(); return dentry; } } - spin_unlock(&dcache_lock); + unlock_dcache(); return NULL; } diff -durN -X dontdiff linux/fs/autofs4/root.c linux-2.4.18preempt-mutex-pi2/fs/autofs4/root.c --- linux/fs/autofs4/root.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/autofs4/root.c Sat Nov 2 00:07:11 2002 @@ -119,15 +119,15 @@ /* If this is an unused directory that isn't a mount point, bitch at the daemon and fix it in user space */ - spin_lock(&dcache_lock); + lock_dcache(); if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { DPRINTK(("try_to_fill_entry: mounting existing dir\n")); - spin_unlock(&dcache_lock); + unlock_dcache(); return autofs4_wait(sbi, &dentry->d_name, NFY_MOUNT) == 0; } - spin_unlock(&dcache_lock); + unlock_dcache(); /* We don't update the usages for the autofs daemon itself, this is necessary for recursive autofs mounts */ @@ -167,19 +167,19 @@ ino = autofs4_dentry_ino(dentry); /* Check for a non-mountpoint directory with no contents */ - spin_lock(&dcache_lock); + lock_dcache(); if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) && list_empty(&dentry->d_subdirs)) { DPRINTK(("autofs_root_revalidate: dentry=%p %.*s, emptydir\n", dentry, dentry->d_name.len, dentry->d_name.name)); - spin_unlock(&dcache_lock); + unlock_dcache(); if (oz_mode) return 1; else return try_to_fill_dentry(dentry, dir->i_sb, sbi); } - spin_unlock(&dcache_lock); + unlock_dcache(); /* Update the usage list */ if (!oz_mode) @@ -398,13 +398,13 @@ if (!autofs4_oz_mode(sbi)) return -EACCES; - spin_lock(&dcache_lock); + lock_dcache(); if (!list_empty(&dentry->d_subdirs)) { - spin_unlock(&dcache_lock); + unlock_dcache(); return -ENOTEMPTY; } list_del_init(&dentry->d_hash); - spin_unlock(&dcache_lock); + unlock_dcache(); dput(ino->dentry); diff -durN -X dontdiff linux/fs/coda/cache.c linux-2.4.18preempt-mutex-pi2/fs/coda/cache.c --- linux/fs/coda/cache.c Thu Sep 19 17:06:32 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/coda/cache.c Sat Nov 2 00:07:07 2002 @@ -96,7 +96,7 @@ struct list_head *child; struct dentry *de; - spin_lock(&dcache_lock); + lock_dcache(); list_for_each(child, &parent->d_subdirs) { de = list_entry(child, struct dentry, d_child); @@ -108,7 +108,7 @@ de->d_parent->d_name.len, de->d_parent->d_name.name); coda_flag_inode(de->d_inode, flag); } - spin_unlock(&dcache_lock); + unlock_dcache(); return; } diff -durN -X dontdiff linux/fs/dcache.c linux-2.4.18preempt-mutex-pi2/fs/dcache.c --- linux/fs/dcache.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/dcache.c Sat Nov 2 00:07:10 2002 @@ -23,13 +23,19 @@ #include #include #include +#include #include #define DCACHE_PARANOIA 1 /* #define DCACHE_DEBUG 1 */ -spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; +#ifdef CONFIG_DCACHE_MTX +DECLARE_P_MUTEX(dcache_mtx); +#else +spinlock_t dcache_mtx __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; +#endif + /* Right now the dcache depends on the kernel lock */ #define check_lock() if (!kernel_locked()) BUG() @@ -77,13 +83,13 @@ if (inode) { dentry->d_inode = NULL; list_del_init(&dentry->d_alias); - spin_unlock(&dcache_lock); + unlock_dcache(); if (dentry->d_op && dentry->d_op->d_iput) dentry->d_op->d_iput(dentry, inode); else iput(inode); } else - spin_unlock(&dcache_lock); + unlock_dcache(); } /* @@ -121,7 +127,7 @@ return; repeat: - if (!atomic_dec_and_lock(&dentry->d_count, &dcache_lock)) + if (!atomic_dec_and_lock_dcache(&dentry->d_count)) return; /* dput on a free dentry? */ @@ -139,7 +145,7 @@ goto kill_it; list_add(&dentry->d_lru, &dentry_unused); dentry_stat.nr_unused++; - spin_unlock(&dcache_lock); + unlock_dcache(); return; unhash_it: @@ -176,9 +182,9 @@ /* * If it's already been dropped, return OK. */ - spin_lock(&dcache_lock); + lock_dcache(); if (list_empty(&dentry->d_hash)) { - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } /* @@ -186,9 +192,9 @@ * to get rid of unused child entries. */ if (!list_empty(&dentry->d_subdirs)) { - spin_unlock(&dcache_lock); + unlock_dcache(); shrink_dcache_parent(dentry); - spin_lock(&dcache_lock); + lock_dcache(); } /* @@ -203,13 +209,13 @@ */ if (atomic_read(&dentry->d_count) > 1) { if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { - spin_unlock(&dcache_lock); + unlock_dcache(); return -EBUSY; } } list_del_init(&dentry->d_hash); - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } @@ -245,7 +251,7 @@ struct list_head *head, *next, *tmp; struct dentry *alias; - spin_lock(&dcache_lock); + lock_dcache(); head = &inode->i_dentry; next = inode->i_dentry.next; while (next != head) { @@ -254,11 +260,11 @@ alias = list_entry(tmp, struct dentry, d_alias); if (!list_empty(&alias->d_hash)) { __dget_locked(alias); - spin_unlock(&dcache_lock); + unlock_dcache(); return alias; } } - spin_unlock(&dcache_lock); + unlock_dcache(); return NULL; } @@ -270,19 +276,19 @@ { struct list_head *tmp, *head = &inode->i_dentry; restart: - spin_lock(&dcache_lock); + lock_dcache(); tmp = head; while ((tmp = tmp->next) != head) { struct dentry *dentry = list_entry(tmp, struct dentry, d_alias); if (!atomic_read(&dentry->d_count)) { __dget_locked(dentry); - spin_unlock(&dcache_lock); + unlock_dcache(); d_drop(dentry); dput(dentry); goto restart; } } - spin_unlock(&dcache_lock); + unlock_dcache(); } /* @@ -302,7 +308,7 @@ d_free(dentry); if (parent != dentry) dput(parent); - spin_lock(&dcache_lock); + lock_dcache(); } /** @@ -320,7 +326,7 @@ void prune_dcache(int count) { - spin_lock(&dcache_lock); + lock_dcache(); for (;;) { struct dentry *dentry; struct list_head *tmp; @@ -348,7 +354,7 @@ if (!--count) break; } - spin_unlock(&dcache_lock); + unlock_dcache(); } /* @@ -382,7 +388,7 @@ * Pass one ... move the dentries for the specified * superblock to the most recent end of the unused list. */ - spin_lock(&dcache_lock); + lock_dcache(); next = dentry_unused.next; while (next != &dentry_unused) { tmp = next; @@ -412,7 +418,7 @@ prune_one_dentry(dentry); goto repeat; } - spin_unlock(&dcache_lock); + unlock_dcache(); } /* @@ -434,7 +440,7 @@ struct dentry *this_parent = parent; struct list_head *next; - spin_lock(&dcache_lock); + lock_dcache(); if (d_mountpoint(parent)) goto positive; repeat: @@ -460,10 +466,10 @@ this_parent = this_parent->d_parent; goto resume; } - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; /* No mount points found in tree */ positive: - spin_unlock(&dcache_lock); + unlock_dcache(); return 1; } @@ -480,7 +486,7 @@ struct list_head *next; int found = 0; - spin_lock(&dcache_lock); + lock_dcache(); repeat: next = this_parent->d_subdirs.next; resume: @@ -517,7 +523,7 @@ #endif goto resume; } - spin_unlock(&dcache_lock); + unlock_dcache(); return found; } @@ -624,9 +630,9 @@ if (parent) { dentry->d_parent = dget(parent); dentry->d_sb = parent->d_sb; - spin_lock(&dcache_lock); + lock_dcache(); list_add(&dentry->d_child, &parent->d_subdirs); - spin_unlock(&dcache_lock); + unlock_dcache(); } else INIT_LIST_HEAD(&dentry->d_child); @@ -652,11 +658,11 @@ void d_instantiate(struct dentry *entry, struct inode * inode) { if (!list_empty(&entry->d_alias)) BUG(); - spin_lock(&dcache_lock); + lock_dcache(); if (inode) list_add(&entry->d_alias, &inode->i_dentry); entry->d_inode = inode; - spin_unlock(&dcache_lock); + unlock_dcache(); } /** @@ -709,7 +715,7 @@ struct list_head *head = d_hash(parent,hash); struct list_head *tmp; - spin_lock(&dcache_lock); + lock_dcache(); tmp = head->next; for (;;) { struct dentry * dentry = list_entry(tmp, struct dentry, d_hash); @@ -731,10 +737,10 @@ } __dget_locked(dentry); dentry->d_vfs_flags |= DCACHE_REFERENCED; - spin_unlock(&dcache_lock); + unlock_dcache(); return dentry; } - spin_unlock(&dcache_lock); + unlock_dcache(); return NULL; } @@ -770,16 +776,16 @@ if (dentry->d_parent != dparent) goto out; - spin_lock(&dcache_lock); + lock_dcache(); lhp = base = d_hash(dparent, dentry->d_name.hash); while ((lhp = lhp->next) != base) { if (dentry == list_entry(lhp, struct dentry, d_hash)) { __dget_locked(dentry); - spin_unlock(&dcache_lock); + unlock_dcache(); return 1; } } - spin_unlock(&dcache_lock); + unlock_dcache(); out: return 0; } @@ -810,12 +816,12 @@ /* * Are we the only user? */ - spin_lock(&dcache_lock); + lock_dcache(); if (atomic_read(&dentry->d_count) == 1) { dentry_iput(dentry); return; } - spin_unlock(&dcache_lock); + unlock_dcache(); /* * If not, just drop the dentry and let dput @@ -835,9 +841,9 @@ { struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash); if (!list_empty(&entry->d_hash)) BUG(); - spin_lock(&dcache_lock); + lock_dcache(); list_add(&entry->d_hash, list); - spin_unlock(&dcache_lock); + unlock_dcache(); } #define do_switch(x,y) do { \ @@ -903,7 +909,7 @@ if (!dentry->d_inode) printk(KERN_WARNING "VFS: moving negative dcache entry\n"); - spin_lock(&dcache_lock); + lock_dcache(); /* Move the dentry to the target hash queue */ list_del(&dentry->d_hash); list_add(&dentry->d_hash, &target->d_hash); @@ -923,7 +929,7 @@ /* And add them back to the (new) parent lists */ list_add(&target->d_child, &target->d_parent->d_subdirs); list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); - spin_unlock(&dcache_lock); + unlock_dcache(); } /** @@ -1033,13 +1039,13 @@ error = -ENOENT; /* Has the current directory has been unlinked? */ - spin_lock(&dcache_lock); + lock_dcache(); if (pwd->d_parent == pwd || !list_empty(&pwd->d_hash)) { unsigned long len; char * cwd; cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE); - spin_unlock(&dcache_lock); + unlock_dcache(); error = -ERANGE; len = PAGE_SIZE + page - cwd; @@ -1049,7 +1055,7 @@ error = -EFAULT; } } else - spin_unlock(&dcache_lock); + unlock_dcache(); dput(pwd); mntput(pwdmnt); dput(root); @@ -1097,7 +1103,7 @@ struct dentry *this_parent = root; struct list_head *next; - spin_lock(&dcache_lock); + lock_dcache(); repeat: next = this_parent->d_subdirs.next; resume: @@ -1119,7 +1125,7 @@ this_parent = this_parent->d_parent; goto resume; } - spin_unlock(&dcache_lock); + unlock_dcache(); } /** diff -durN -X dontdiff linux/fs/devfs/base.c linux-2.4.18preempt-mutex-pi2/fs/devfs/base.c --- linux/fs/devfs/base.c Thu Sep 19 17:06:34 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/devfs/base.c Sat Nov 2 00:07:09 2002 @@ -1368,10 +1368,10 @@ { struct dentry *dentry = de->inode.dentry; - if (!dentry) return; - spin_lock (&dcache_lock); + if (!dentry) return; + lock_dcache(); dget_locked (dentry); - spin_unlock (&dcache_lock); + unlock_dcache(); /* Forcefully remove the inode */ if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0; d_drop (dentry); diff -durN -X dontdiff linux/fs/fat/inode.c linux-2.4.18preempt-mutex-pi2/fs/fat/inode.c --- linux/fs/fat/inode.c Thu Sep 19 17:06:30 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/fat/inode.c Sat Nov 2 00:07:05 2002 @@ -484,18 +484,18 @@ * well-connected, but it is easiest to just copy the * code. */ - spin_lock(&dcache_lock); + lock_dcache(); for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { result = list_entry(lp,struct dentry, d_alias); if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) { dget_locked(result); result->d_vfs_flags |= DCACHE_REFERENCED; - spin_unlock(&dcache_lock); + unlock_dcache(); iput(inode); return result; } } - spin_unlock(&dcache_lock); + unlock_dcache(); result = d_alloc_root(inode); if (result == NULL) { iput(inode); diff -durN -X dontdiff linux/fs/namei.c linux-2.4.18preempt-mutex-pi2/fs/namei.c --- linux/fs/namei.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/namei.c Sat Nov 2 00:07:11 2002 @@ -358,15 +358,15 @@ { struct vfsmount *parent; struct dentry *dentry; - spin_lock(&dcache_lock); + lock_dcache(); parent=(*mnt)->mnt_parent; if (parent == *mnt) { - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } mntget(parent); dentry=dget((*mnt)->mnt_mountpoint); - spin_unlock(&dcache_lock); + unlock_dcache(); dput(*base); *base = dentry; mntput(*mnt); @@ -383,17 +383,17 @@ { struct vfsmount *mounted; - spin_lock(&dcache_lock); + lock_dcache(); mounted = lookup_mnt(*mnt, *dentry); if (mounted) { *mnt = mntget(mounted); - spin_unlock(&dcache_lock); + unlock_dcache(); dput(*dentry); mntput(mounted->mnt_parent); *dentry = dget(mounted->mnt_root); return 1; } - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } @@ -414,22 +414,22 @@ break; } read_unlock(¤t->fs->lock); - spin_lock(&dcache_lock); + lock_dcache(); if (nd->dentry != nd->mnt->mnt_root) { dentry = dget(nd->dentry->d_parent); - spin_unlock(&dcache_lock); + unlock_dcache(); dput(nd->dentry); nd->dentry = dentry; break; } parent=nd->mnt->mnt_parent; if (parent == nd->mnt) { - spin_unlock(&dcache_lock); + unlock_dcache(); break; } mntget(parent); dentry=dget(nd->mnt->mnt_mountpoint); - spin_unlock(&dcache_lock); + unlock_dcache(); dput(nd->dentry); nd->dentry = dentry; mntput(nd->mnt); diff -durN -X dontdiff linux/fs/namespace.c linux-2.4.18preempt-mutex-pi2/fs/namespace.c --- linux/fs/namespace.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/namespace.c Sat Nov 2 00:07:11 2002 @@ -96,10 +96,10 @@ static int check_mnt(struct vfsmount *mnt) { - spin_lock(&dcache_lock); + lock_dcache(); while (mnt->mnt_parent != mnt) mnt = mnt->mnt_parent; - spin_unlock(&dcache_lock); + unlock_dcache(); return mnt == root_vfsmnt; } @@ -277,15 +277,15 @@ mnt = list_entry(kill.next, struct vfsmount, mnt_list); list_del_init(&mnt->mnt_list); if (mnt->mnt_parent == mnt) { - spin_unlock(&dcache_lock); + unlock_dcache(); } else { struct nameidata old_nd; detach_mnt(mnt, &old_nd); - spin_unlock(&dcache_lock); + unlock_dcache(); path_release(&old_nd); } mntput(mnt); - spin_lock(&dcache_lock); + lock_dcache(); } } @@ -334,16 +334,16 @@ } down(&mount_sem); - spin_lock(&dcache_lock); + lock_dcache(); if (atomic_read(&sb->s_active) == 1) { /* last instance - try to be smart */ - spin_unlock(&dcache_lock); + unlock_dcache(); lock_kernel(); DQUOT_OFF(sb); acct_auto_close(sb->s_dev); unlock_kernel(); - spin_lock(&dcache_lock); + lock_dcache(); } retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { @@ -351,7 +351,7 @@ umount_tree(mnt); retval = 0; } - spin_unlock(&dcache_lock); + unlock_dcache(); up(&mount_sem); return retval; } @@ -447,17 +447,17 @@ q = clone_mnt(p, p->mnt_root); if (!q) goto Enomem; - spin_lock(&dcache_lock); + lock_dcache(); list_add_tail(&q->mnt_list, &res->mnt_list); attach_mnt(q, &nd); - spin_unlock(&dcache_lock); + unlock_dcache(); } return res; Enomem: if (res) { - spin_lock(&dcache_lock); + lock_dcache(); umount_tree(res); - spin_unlock(&dcache_lock); + unlock_dcache(); } return NULL; } @@ -478,7 +478,7 @@ if (IS_DEADDIR(nd->dentry->d_inode)) goto out_unlock; - spin_lock(&dcache_lock); + lock_dcache(); if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) { struct list_head head; attach_mnt(mnt, nd); @@ -487,7 +487,7 @@ mntget(mnt); err = 0; } - spin_unlock(&dcache_lock); + unlock_dcache(); out_unlock: up(&nd->dentry->d_inode->i_zombie); return err; @@ -523,9 +523,9 @@ if (mnt) { err = graft_tree(mnt, nd); if (err) { - spin_lock(&dcache_lock); + lock_dcache(); umount_tree(mnt); - spin_unlock(&dcache_lock); + unlock_dcache(); } else mntput(mnt); } @@ -589,7 +589,7 @@ if (IS_DEADDIR(nd->dentry->d_inode)) goto out1; - spin_lock(&dcache_lock); + lock_dcache(); if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry)) goto out2; @@ -613,7 +613,7 @@ detach_mnt(old_nd.mnt, &parent_nd); attach_mnt(old_nd.mnt, nd); out2: - spin_unlock(&dcache_lock); + unlock_dcache(); out1: up(&nd->dentry->d_inode->i_zombie); out: @@ -888,7 +888,7 @@ if (new_nd.mnt->mnt_root != new_nd.dentry) goto out2; /* not a mountpoint */ tmp = old_nd.mnt; /* make sure we can reach put_old from new_root */ - spin_lock(&dcache_lock); + lock_dcache(); if (tmp != new_nd.mnt) { for (;;) { if (tmp->mnt_parent == tmp) @@ -905,7 +905,7 @@ detach_mnt(user_nd.mnt, &root_parent); attach_mnt(user_nd.mnt, &old_nd); attach_mnt(new_nd.mnt, &root_parent); - spin_unlock(&dcache_lock); + unlock_dcache(); chroot_fs_refs(&user_nd, &new_nd); error = 0; path_release(&root_parent); @@ -921,7 +921,7 @@ unlock_kernel(); return error; out3: - spin_unlock(&dcache_lock); + unlock_dcache(); goto out2; } @@ -1057,9 +1057,9 @@ } path_release(&devfs_nd); } - spin_lock(&dcache_lock); + lock(dcache); detach_mnt(old_rootmnt, &parent_nd); - spin_unlock(&dcache_lock); + unlock_dcache(); ROOT_DEV = new_root_dev; mount_root(); #if 1 @@ -1082,9 +1082,9 @@ blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS); printk(KERN_NOTICE "Trying to unmount old root ... "); if (!blivet) { - spin_lock(&dcache_lock); + lock(dcache); list_del_init(&old_rootmnt->mnt_list); - spin_unlock(&dcache_lock); + unlock_dcache(); mntput(old_rootmnt); mntput(old_rootmnt); blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0); @@ -1101,14 +1101,14 @@ return error; } - spin_lock(&dcache_lock); + lock(dcache); attach_mnt(old_rootmnt, &nd); if (new_devname) { if (old_rootmnt->mnt_devname) kfree(old_rootmnt->mnt_devname); old_rootmnt->mnt_devname = new_devname; } - spin_unlock(&dcache_lock); + unlock_dcache(); /* put the old stuff */ path_release(&parent_nd); diff -durN -X dontdiff linux/fs/ncpfs/dir.c linux-2.4.18preempt-mutex-pi2/fs/ncpfs/dir.c --- linux/fs/ncpfs/dir.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/ncpfs/dir.c Sat Nov 2 00:07:10 2002 @@ -345,7 +345,7 @@ } /* If a pointer is invalid, we search the dentry. */ - spin_lock(&dcache_lock); + lock_dcache(); next = parent->d_subdirs.next; while (next != &parent->d_subdirs) { dent = list_entry(next, struct dentry, d_child); @@ -354,12 +354,12 @@ dget_locked(dent); else dent = NULL; - spin_unlock(&dcache_lock); + unlock_dcache(); goto out; } next = next->next; } - spin_unlock(&dcache_lock); + unlock_dcache(); return NULL; out: diff -durN -X dontdiff linux/fs/ncpfs/ncplib_kernel.h linux-2.4.18preempt-mutex-pi2/fs/ncpfs/ncplib_kernel.h --- linux/fs/ncpfs/ncplib_kernel.h Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/ncpfs/ncplib_kernel.h Sat Nov 2 00:07:10 2002 @@ -158,7 +158,7 @@ struct list_head *next; struct dentry *dentry; - spin_lock(&dcache_lock); + lock_dcache(); next = parent->d_subdirs.next; while (next != &parent->d_subdirs) { dentry = list_entry(next, struct dentry, d_child); @@ -170,7 +170,7 @@ next = next->next; } - spin_unlock(&dcache_lock); + unlock_dcache(); } static inline void @@ -180,7 +180,7 @@ struct list_head *next; struct dentry *dentry; - spin_lock(&dcache_lock); + lock_dcache(); next = parent->d_subdirs.next; while (next != &parent->d_subdirs) { dentry = list_entry(next, struct dentry, d_child); @@ -188,7 +188,7 @@ ncp_age_dentry(server, dentry); next = next->next; } - spin_unlock(&dcache_lock); + unlock_dcache(); } struct ncp_cache_head { diff -durN -X dontdiff linux/fs/nfsd/nfsfh.c linux-2.4.18preempt-mutex-pi2/fs/nfsd/nfsfh.c --- linux/fs/nfsd/nfsfh.c Thu Sep 19 17:06:34 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/nfsd/nfsfh.c Sat Nov 2 00:07:07 2002 @@ -158,18 +158,18 @@ /* now to find a dentry. * If possible, get a well-connected one */ - spin_lock(&dcache_lock); + lock_dcache(); for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { result = list_entry(lp,struct dentry, d_alias); if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) { dget_locked(result); result->d_vfs_flags |= DCACHE_REFERENCED; - spin_unlock(&dcache_lock); + unlock_dcache(); iput(inode); return result; } } - spin_unlock(&dcache_lock); + unlock_dcache(); result = d_alloc_root(inode); if (result == NULL) { iput(inode); @@ -225,10 +225,10 @@ /* tdentry will have been made a "child" of target (the parent of target) * make it an IS_ROOT instead */ - spin_lock(&dcache_lock); + lock_dcache(); list_del_init(&tdentry->d_child); tdentry->d_parent = tdentry; - spin_unlock(&dcache_lock); + unlock_dcache(); d_rehash(target); dput(tdentry); @@ -240,7 +240,7 @@ while (target) { target->d_flags &= ~DCACHE_NFSD_DISCONNECTED; parent = target; - spin_lock(&dcache_lock); + lock_dcache(); if (list_empty(&parent->d_subdirs)) target = NULL; else { @@ -253,7 +253,7 @@ parent->d_name.name, target->d_name.name); #endif } - spin_unlock(&dcache_lock); + unlock_dcache(); } } return 0; @@ -288,7 +288,7 @@ * else make a root dentry */ struct list_head *aliases = &tdentry->d_inode->i_dentry; - spin_lock(&dcache_lock); + lock_dcache(); if (aliases->next != aliases) { pdentry = list_entry(aliases->next, struct dentry, d_alias); if (pdentry == tdentry) @@ -297,7 +297,7 @@ pdentry = NULL; if (pdentry) dget_locked(pdentry); } - spin_unlock(&dcache_lock); + unlock_dcache(); if (pdentry == NULL) { pdentry = d_alloc_root(tdentry->d_inode); if (pdentry) { @@ -345,17 +345,17 @@ * parent by a lookup. In this case return that dentry. Caller must * notice and act accordingly */ - spin_lock(&dcache_lock); + lock_dcache(); list_for_each(lp, &child->d_inode->i_dentry) { struct dentry *tmp = list_entry(lp,struct dentry, d_alias); if (!list_empty(&tmp->d_hash) && tmp->d_parent == parent) { child = dget_locked(tmp); - spin_unlock(&dcache_lock); + unlock_dcache(); goto out; } } - spin_unlock(&dcache_lock); + unlock_dcache(); /* now we need that name. If there was an error getting it, now is th * time to bail out. diff -durN -X dontdiff linux/fs/proc/base.c linux-2.4.18preempt-mutex-pi2/fs/proc/base.c --- linux/fs/proc/base.c Thu Sep 19 17:06:34 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/proc/base.c Sat Nov 2 00:07:08 2002 @@ -197,7 +197,7 @@ base = dget(current->fs->root); read_unlock(¤t->fs->lock); - spin_lock(&dcache_lock); + lock_dcache(); de = root; mnt = vfsmnt; @@ -210,7 +210,7 @@ if (!is_subdir(de, base)) goto out; - spin_unlock(&dcache_lock); + unlock_dcache(); exit: dput(base); @@ -219,7 +219,7 @@ mntput(mnt); return res; out: - spin_unlock(&dcache_lock); + unlock_dcache(); res = -EACCES; goto exit; } diff -durN -X dontdiff linux/fs/ramfs/inode.c linux-2.4.18preempt-mutex-pi2/fs/ramfs/inode.c --- linux/fs/ramfs/inode.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/ramfs/inode.c Sat Nov 2 00:07:10 2002 @@ -190,19 +190,19 @@ { struct list_head *list; - spin_lock(&dcache_lock); + lock_dcache(); list = dentry->d_subdirs.next; while (list != &dentry->d_subdirs) { struct dentry *de = list_entry(list, struct dentry, d_child); if (ramfs_positive(de)) { - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } list = list->next; } - spin_unlock(&dcache_lock); + unlock_dcache(); return 1; } diff -durN -X dontdiff linux/fs/readdir.c linux-2.4.18preempt-mutex-pi2/fs/readdir.c --- linux/fs/readdir.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/readdir.c Sat Nov 2 00:07:11 2002 @@ -62,12 +62,12 @@ struct list_head *list; int j = i-2; - spin_lock(&dcache_lock); + lock_dcache(); list = dentry->d_subdirs.next; for (;;) { if (list == &dentry->d_subdirs) { - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } if (!j) @@ -80,16 +80,16 @@ struct dentry *de = list_entry(list, struct dentry, d_child); if (!list_empty(&de->d_hash) && de->d_inode) { - spin_unlock(&dcache_lock); + unlock_dcache(); if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0) break; - spin_lock(&dcache_lock); + lock_dcache(); } filp->f_pos++; list = list->next; if (list != &dentry->d_subdirs) continue; - spin_unlock(&dcache_lock); + unlock_dcache(); break; } } diff -durN -X dontdiff linux/fs/reiserfs/inode.c linux-2.4.18preempt-mutex-pi2/fs/reiserfs/inode.c --- linux/fs/reiserfs/inode.c Thu Sep 19 17:06:34 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/reiserfs/inode.c Sat Nov 2 00:07:09 2002 @@ -1288,18 +1288,18 @@ /* now to find a dentry. * If possible, get a well-connected one */ - spin_lock(&dcache_lock); + lock_dcache(); for (lp = inode->i_dentry.next; lp != &inode->i_dentry ; lp=lp->next) { result = list_entry(lp,struct dentry, d_alias); if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) { dget_locked(result); result->d_vfs_flags |= DCACHE_REFERENCED; - spin_unlock(&dcache_lock); + unlock_dcache(); iput(inode); return result; } } - spin_unlock(&dcache_lock); + unlock_dcache(); result = d_alloc_root(inode); if (result == NULL) { iput(inode); diff -durN -X dontdiff linux/fs/smbfs/cache.c linux-2.4.18preempt-mutex-pi2/fs/smbfs/cache.c --- linux/fs/smbfs/cache.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/smbfs/cache.c Sat Nov 2 00:07:10 2002 @@ -62,7 +62,7 @@ struct list_head *next; struct dentry *dentry; - spin_lock(&dcache_lock); + lock_dcache(); next = parent->d_subdirs.next; while (next != &parent->d_subdirs) { dentry = list_entry(next, struct dentry, d_child); @@ -70,7 +70,7 @@ smb_age_dentry(server, dentry); next = next->next; } - spin_unlock(&dcache_lock); + unlock_dcache(); } /* @@ -96,7 +96,7 @@ } /* If a pointer is invalid, we search the dentry. */ - spin_lock(&dcache_lock); + lock_dcache(); next = parent->d_subdirs.next; while (next != &parent->d_subdirs) { dent = list_entry(next, struct dentry, d_child); @@ -111,7 +111,7 @@ } dent = NULL; out_unlock: - spin_unlock(&dcache_lock); + unlock_dcache(); return dent; } diff -durN -X dontdiff linux/fs/umsdos/dir.c linux-2.4.18preempt-mutex-pi2/fs/umsdos/dir.c --- linux/fs/umsdos/dir.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/umsdos/dir.c Sat Nov 2 00:07:11 2002 @@ -650,9 +650,9 @@ read_lock(¤t->fs->lock); old_root = dget(current->fs->root); read_unlock(¤t->fs->lock); - spin_lock(&dcache_lock); + lock_dcache(); path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */ - spin_unlock(&dcache_lock); + unlock_dcache(); if (*path == '/') path++; /* skip leading '/' */ diff -durN -X dontdiff linux/fs/vfat/namei.c linux-2.4.18preempt-mutex-pi2/fs/vfat/namei.c --- linux/fs/vfat/namei.c Thu Sep 19 17:06:34 2002 +++ linux-2.4.18preempt-mutex-pi2/fs/vfat/namei.c Sat Nov 2 00:07:09 2002 @@ -75,12 +75,12 @@ static int vfat_revalidate(struct dentry *dentry, int flags) { PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name)); - spin_lock(&dcache_lock); + lock_dcache(); if (dentry->d_time == dentry->d_parent->d_inode->i_version) { - spin_unlock(&dcache_lock); + unlock_dcache(); return 1; } - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } diff -durN -X dontdiff linux/include/linux/dcache.h linux-2.4.18preempt-mutex-pi2/include/linux/dcache.h --- linux/include/linux/dcache.h Thu Sep 19 17:22:50 2002 +++ linux-2.4.18preempt-mutex-pi2/include/linux/dcache.h Sun Nov 3 03:59:18 2002 @@ -5,6 +5,7 @@ #include #include +#include /* * linux/include/linux/dcache.h @@ -124,7 +125,18 @@ */ #define DCACHE_REFERENCED 0x0008 /* Recently used, don't discard. */ -extern spinlock_t dcache_lock; +#ifdef CONFIG_DCACHE_MTX +extern p_mutex_t dcache_mtx; +#define lock_dcache() p_mutex_down(&dcache_mtx) +#define unlock_dcache() p_mutex_up(&dcache_mtx) +#define atomic_dec_and_lock_dcache(x) atomic_dec_and_mutex_lock(x, &dcache_mtx) +#else +extern spinlock_t dcache_mtx; +#define lock_dcache() spin_lock(&dcache_mtx) +#define unlock_dcache() spin_unlock(&dcache_mtx) +#define atomic_dec_and_lock_dcache(x) atomic_dec_and_lock(x, &dcache_mtx) +#endif + static __inline__ int dname_external(struct dentry *d) { @@ -274,10 +286,10 @@ static __inline__ void d_drop(struct dentry * dentry) { - spin_lock(&dcache_lock); + lock_dcache(); list_del(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_hash); - spin_unlock(&dcache_lock); + unlock_dcache(); } #endif #endif diff -durN -X dontdiff linux/include/linux/dnotify.h linux-2.4.18preempt-mutex-pi2/include/linux/dnotify.h --- linux/include/linux/dnotify.h Thu Sep 19 17:07:27 2002 +++ linux-2.4.18preempt-mutex-pi2/include/linux/dnotify.h Sat Nov 2 00:08:18 2002 @@ -31,13 +31,13 @@ static inline void dnotify_parent(struct dentry *dentry, unsigned long event) { struct dentry *parent; - spin_lock(&dcache_lock); + lock_dcache(); parent = dentry->d_parent; if (parent->d_inode->i_dnotify_mask & event) { dget(parent); - spin_unlock(&dcache_lock); + unlock_dcache(); __inode_dir_notify(parent->d_inode, event); dput(parent); } else - spin_unlock(&dcache_lock); + unlock_dcache(); } diff -durN -X dontdiff linux/include/linux/pmutex.h linux-2.4.18preempt-mutex-pi2/include/linux/pmutex.h --- linux/include/linux/pmutex.h Thu Jan 1 01:00:00 1970 +++ linux-2.4.18preempt-mutex-pi2/include/linux/pmutex.h Sun Nov 3 03:39:15 2002 @@ -0,0 +1,155 @@ +/* + * pmutex.h -- mutex implementation with priority inheritance + * + * See + * http://inf33-www.informatik.unibw-muenchen.de/research/linux/mutex.html + * for details of the used priority inheritance protocol. + * + * Copyright (C) 2002 Dirk Grambow + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#ifndef __LINUX_PMUTEX_H +#define __LINUX_PMUTEX_H + +#include +#include +#include + +struct p_sleeper_list { + struct list_head list; + struct task_struct *task; +}; + +typedef struct p_sleeper_list p_sleeper_list_t; + +struct p_mutex { + int m_lock, m_missed; + struct list_head m_sleepers; +#ifdef CONFIG_MTX_PI + struct task_struct *owner; + unsigned long initial_prio; +#endif +}; + +typedef struct p_mutex p_mutex_t; + +#ifdef CONFIG_MTX_PI +struct mtx_set { + struct list_head list; + p_mutex_t *mtx; +}; + +typedef struct mtx_set mtx_set_t; +#endif + +extern int atomic_dec_and_mutex_lock(atomic_t *atomic, p_mutex_t *mtx); + +#ifdef CONFIG_MTX_PI + +#define DECLARE_P_MUTEX(x) \ +p_mutex_t (x) = { 1, 0, LIST_HEAD_INIT((x).m_sleepers), 0, 0} + +#else + +#define DECLARE_P_MUTEX(x) \ +p_mutex_t (x) = { 1, 0, LIST_HEAD_INIT((x).m_sleepers)} + +#endif + + +static inline void p_mutex_init(p_mutex_t *mtx) +{ + mtx->m_lock = 1; + mtx->m_missed = 0; + INIT_LIST_HEAD(&mtx->m_sleepers); +#ifdef CONFIG_MTX_PI + mtx->owner = 0; + mtx->initial_prio = 0; +#endif +} + +extern void __p_mutex_down(p_mutex_t *mtx); +extern void __p_mutex_up(p_mutex_t *mtx); + +/* + * The following i386 p_mutex_down() and p_mutex_up() implementations are + * based on their arch/i386/kernel/semaphore.c counterparts. + */ + +static inline void p_mutex_down(p_mutex_t *mtx) +{ + __asm__ __volatile__ ( + "\t" +#ifdef CONFIG_MTX_PI + "pushfl\n\t" + "cli\n\t" +#endif + LOCK "decl %0\n\t" + "js 2f\n" +#ifdef CONFIG_MTX_PI + "\tmovl %%esp, %1\n\t" + "andl $-8192, %1\n\t" + "popfl\n" +#endif + "1:\n" + ".subsection 1\n" + "2:\t" +#ifdef CONFIG_MTX_PI + "popfl\n\t" +#endif + "pushl %%eax\n\t" + "pushl %%edx\n\t" + "pushl %%ecx\n\t" + "call __p_mutex_down\n\t" + "popl %%ecx\n\t" + "popl %%edx\n\t" + "popl %%eax\n\t" + "jmp 1b\n" + ".subsection 0\n" + :"=m" (mtx->m_lock) +#ifdef CONFIG_MTX_PI + , "=m" (mtx->owner) +#endif + :"c" (mtx) + :"memory"); +} + + +static inline void p_mutex_up(p_mutex_t *mtx) +{ + __asm__ __volatile__ ( + "\t" + LOCK "incl %0\n\t" + "jle 2f\n" + "1:\n" + ".subsection 1\n" + "2:\tpushl %%eax\n\t" + "pushl %%edx\n\t" + "pushl %%ecx\n\t" + "call __p_mutex_up\n\t" + "popl %%ecx\n\t" + "popl %%edx\n\t" + "popl %%eax\n\t" + "jmp 1b\n" + ".subsection 0\n" + :"=m" (mtx->m_lock) + :"c" (mtx) + :"memory"); +} +#endif diff -durN -X dontdiff linux/include/linux/sched.h linux-2.4.18preempt-mutex-pi2/include/linux/sched.h --- linux/include/linux/sched.h Thu Sep 19 17:22:50 2002 +++ linux-2.4.18preempt-mutex-pi2/include/linux/sched.h Sun Nov 3 03:59:18 2002 @@ -26,6 +26,7 @@ #include #include #include +#include struct exec_domain; @@ -331,6 +332,11 @@ unsigned int allocation_order, nr_local_pages; unsigned long flags; +#ifdef CONFIG_MTX_PI + struct list_head mtx_set; + p_mutex_t *waiting_mtx; +#endif + /* task state */ struct linux_binfmt *binfmt; int exit_code, exit_signal; @@ -924,9 +930,9 @@ rootmnt = mntget(current->fs->rootmnt); root = dget(current->fs->root); read_unlock(¤t->fs->lock); - spin_lock(&dcache_lock); + lock_dcache(); res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen); - spin_unlock(&dcache_lock); + unlock_dcache(); dput(root); mntput(rootmnt); return res; diff -durN -X dontdiff linux/kernel/Makefile linux-2.4.18preempt-mutex-pi2/kernel/Makefile --- linux/kernel/Makefile Thu Sep 19 17:07:20 2002 +++ linux-2.4.18preempt-mutex-pi2/kernel/Makefile Sat Nov 2 00:08:10 2002 @@ -19,6 +19,7 @@ obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += ksyms.o obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_PREEMPT) += pmutex.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra , the -fno-omit-frame-pointer is diff -durN -X dontdiff linux/kernel/fork.c linux-2.4.18preempt-mutex-pi2/kernel/fork.c --- linux/kernel/fork.c Thu Sep 19 17:09:16 2002 +++ linux-2.4.18preempt-mutex-pi2/kernel/fork.c Sat Nov 2 01:04:12 2002 @@ -621,6 +621,12 @@ */ p->preempt_count = 1; #endif + +#ifdef CONFIG_MTX_PI + INIT_LIST_HEAD(&p->mtx_set); + p->waiting_mtx = 0; +#endif + p->did_exec = 0; p->swappable = 0; p->state = TASK_UNINTERRUPTIBLE; diff -durN -X dontdiff linux/kernel/ksyms.c linux-2.4.18preempt-mutex-pi2/kernel/ksyms.c --- linux/kernel/ksyms.c Thu Sep 19 17:09:16 2002 +++ linux-2.4.18preempt-mutex-pi2/kernel/ksyms.c Sat Nov 2 00:08:10 2002 @@ -47,6 +47,7 @@ #include #include #include +#include #include #if defined(CONFIG_PROC_FS) @@ -148,7 +149,9 @@ EXPORT_SYMBOL(lookup_one_len); EXPORT_SYMBOL(lookup_hash); EXPORT_SYMBOL(sys_close); -EXPORT_SYMBOL(dcache_lock); +EXPORT_SYMBOL(dcache_mtx); +EXPORT_SYMBOL(__p_mutex_down); +EXPORT_SYMBOL(__p_mutex_up); EXPORT_SYMBOL(d_alloc_root); EXPORT_SYMBOL(d_delete); EXPORT_SYMBOL(dget_locked); diff -durN -X dontdiff linux/kernel/pmutex.c linux-2.4.18preempt-mutex-pi2/kernel/pmutex.c --- linux/kernel/pmutex.c Thu Jan 1 01:00:00 1970 +++ linux-2.4.18preempt-mutex-pi2/kernel/pmutex.c Sun Nov 3 04:04:17 2002 @@ -0,0 +1,166 @@ +/* + * pmutex.c -- mutex implementation with priority inheritance + * + * See + * http://inf33-www.informatik.unibw-muenchen.de/research/linux/mutex.html + * for details of the used priority inheritance protocol. + * + * Copyright (C) 2002 Dirk Grambow + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +#include +#include +#include + +static spinlock_t m_spin_lock = SPIN_LOCK_UNLOCKED; + +void __p_mutex_down(p_mutex_t *mtx) +{ + p_sleeper_list_t new; + +#ifdef CONFIG_MTX_PI + struct list_head *pos; + mtx_set_t new_ms; + p_mutex_t *tmp_mtx, *entry; +#endif + + new.task = current; + + spin_lock(&m_spin_lock); + + if (mtx->m_missed) { + mtx->m_missed = 0; + +#ifdef CONFIG_MTX_PI + mtx->owner = current; +#endif + + spin_unlock(&m_spin_lock); + return; + } + + list_add(&new.list, &mtx->m_sleepers); + +#ifdef CONFIG_MTX_PI + if (current->rt_priority > mtx->owner->rt_priority) { + tmp_mtx = mtx; + do { + list_for_each(pos, &tmp_mtx->owner->mtx_set) { + entry = list_entry(pos, mtx_set_t, list)->mtx; + if (entry == tmp_mtx) { + if (entry->owner->rt_priority < current->rt_priority) + entry->owner->rt_priority = current->rt_priority; + // evtl else goto out + break; + } + } + if (pos == &tmp_mtx->owner->mtx_set) { + if (list_empty(&tmp_mtx->owner->mtx_set)) + tmp_mtx->initial_prio = tmp_mtx->owner->rt_priority; + new_ms.mtx = tmp_mtx; + list_add(&new_ms.list, pos); + if (tmp_mtx->owner->rt_priority == 0) + tmp_mtx->owner->policy = SCHED_FIFO; + tmp_mtx->owner->rt_priority = current->rt_priority; + } + tmp_mtx = tmp_mtx->owner->waiting_mtx; + } while (tmp_mtx != 0); + } + current->waiting_mtx = mtx; +#endif + + current->state = TASK_UNINTERRUPTIBLE; + + spin_unlock(&m_spin_lock); + + schedule(); +} + +#ifdef CONFIG_MTX_PI +static inline int remove_inherited_prio(struct task_struct *t, p_mutex_t *mtx) +{ + struct list_head *pos; + mtx_set_t *entry; + + list_for_each(pos, &t->mtx_set) { + entry = list_entry(pos, mtx_set_t, list); + if (entry->mtx == mtx) + break; + } + if (pos != &t->mtx_set) { + list_del(pos); + return 1; + } + return 0; +} +#endif + +void __p_mutex_up(p_mutex_t *mtx) +{ + struct list_head *pos, *next_entry; + struct task_struct *next, *tmp; + +#ifdef CONFIG_MTX_PI + unsigned long act, highest; +#endif + + spin_lock(&m_spin_lock); + + if (list_empty(&mtx->m_sleepers)) { + mtx->m_missed = 1; + spin_unlock(&m_spin_lock); + return; + } + + + next_entry = mtx->m_sleepers.next; + next = list_entry(next_entry, p_sleeper_list_t, list)->task; + list_for_each(pos, &mtx->m_sleepers) { + tmp = list_entry(pos, p_sleeper_list_t, list)->task; + if (tmp->rt_priority > next->rt_priority) { + next = tmp; + next_entry = pos; + } + } + +#ifdef CONFIG_MTX_PI + if (remove_inherited_prio(current, mtx)) { + if (list_empty(¤t->mtx_set)) { + current->rt_priority = mtx->initial_prio; + if (mtx->initial_prio == 0) + current->policy = SCHED_OTHER; + } else { + highest = 0; + list_for_each(pos, ¤t->mtx_set) { + act = list_entry(pos, mtx_set_t, list)->mtx->owner->rt_priority; + if (act > highest) + highest = act; + } + current->rt_priority = highest; + } + } + mtx->owner = next; + mtx->owner->waiting_mtx = 0; +#endif + + list_del(next_entry); + wake_up_process(next); + + spin_unlock(&m_spin_lock); +} diff -durN -X dontdiff linux/mm/shmem.c linux-2.4.18preempt-mutex-pi2/mm/shmem.c --- linux/mm/shmem.c Thu Sep 19 17:06:35 2002 +++ linux-2.4.18preempt-mutex-pi2/mm/shmem.c Sat Nov 2 00:07:11 2002 @@ -1046,19 +1046,19 @@ { struct list_head *list; - spin_lock(&dcache_lock); + lock_dcache(); list = dentry->d_subdirs.next; while (list != &dentry->d_subdirs) { struct dentry *de = list_entry(list, struct dentry, d_child); if (shmem_positive(de)) { - spin_unlock(&dcache_lock); + unlock_dcache(); return 0; } list = list->next; } - spin_unlock(&dcache_lock); + unlock_dcache(); return 1; }