diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-12-03 13:10:07 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2008-12-03 13:10:07 +1100 |
commit | 71444d6c16faad70bdb884d0f7e8afd67e41134a (patch) | |
tree | 376d97d938bc477b25f12c09612d94fbd0bc5eb7 /lib | |
parent | 9918ff136c44a1c87822793ffee95a243d8d7d60 (diff) | |
parent | aba3e5b25a349f8b4ffc3af859e31cb83314ac9e (diff) |
Merge branch 'quilt/rr'
Conflicts:
arch/x86/kernel/setup.c
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 11 | ||||
-rw-r--r-- | lib/Makefile | 1 | ||||
-rw-r--r-- | lib/find_next_bit.c | 31 | ||||
-rw-r--r-- | lib/is_single_threaded.c | 45 |
4 files changed, 88 insertions, 0 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index fd4118e097f0..fc5f5ee50bc2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -13,6 +13,10 @@ config GENERIC_FIND_FIRST_BIT config GENERIC_FIND_NEXT_BIT bool +config GENERIC_FIND_LAST_BIT + bool + default y + config CRC_CCITT tristate "CRC-CCITT functions" help @@ -159,4 +163,11 @@ config CHECK_SIGNATURE config HAVE_LMB boolean +config CPUMASK_OFFSTACK + bool "Force CPU masks off stack" if DEBUG_PER_CPU_MAPS + help + Use dynamic allocation for cpumask_var_t, instead of putting + them on the stack. This is a bit more expensive, but avoids + stack overflow. + endmenu diff --git a/lib/Makefile b/lib/Makefile index 7cb65d85aeb0..cc8335a921e7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -37,6 +37,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o +lib-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_next_bit.o obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o obj-$(CONFIG_PLIST) += plist.o diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c index 24c59ded47a0..0fc495273924 100644 --- a/lib/find_next_bit.c +++ b/lib/find_next_bit.c @@ -159,6 +159,37 @@ found: EXPORT_SYMBOL(find_first_zero_bit); #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ +#ifdef CONFIG_GENERIC_FIND_LAST_BIT +unsigned long find_last_bit(const unsigned long *addr, unsigned long size) +{ + unsigned long words; + unsigned long tmp; + + /* Start at final word. */ + words = size / BITS_PER_LONG; + + /* Partial final word? */ + if (size & (BITS_PER_LONG-1)) { + tmp = (addr[words] & (~0UL >> (BITS_PER_LONG + - (size & (BITS_PER_LONG-1))))); + if (tmp) + goto found; + } + + while (words) { + tmp = addr[--words]; + if (tmp) { +found: + return words * BITS_PER_LONG + __fls(tmp); + } + } + + /* Not found */ + return size; +} +EXPORT_SYMBOL(find_last_bit); +#endif /* CONFIG_GENERIC_FIND_LAST_BIT */ + #ifdef __BIG_ENDIAN /* include/linux/byteorder does not support "unsigned long" type */ diff --git a/lib/is_single_threaded.c b/lib/is_single_threaded.c new file mode 100644 index 000000000000..f1ed2fe76c65 --- /dev/null +++ b/lib/is_single_threaded.c @@ -0,0 +1,45 @@ +/* Function to determine if a thread group is single threaded or not + * + * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * - Derived from security/selinux/hooks.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include <linux/sched.h> + +/** + * is_single_threaded - Determine if a thread group is single-threaded or not + * @p: A task in the thread group in question + * + * This returns true if the thread group to which a task belongs is single + * threaded, false if it is not. + */ +bool is_single_threaded(struct task_struct *p) +{ + struct task_struct *g, *t; + struct mm_struct *mm = p->mm; + + if (atomic_read(&p->signal->count) != 1) + goto no; + + if (atomic_read(&p->mm->mm_users) != 1) { + read_lock(&tasklist_lock); + do_each_thread(g, t) { + if (t->mm == mm && t != p) + goto no_unlock; + } while_each_thread(g, t); + read_unlock(&tasklist_lock); + } + + return true; + +no_unlock: + read_unlock(&tasklist_lock); +no: + return false; +} |