summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2008-12-03 13:10:07 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2008-12-03 13:10:07 +1100
commit71444d6c16faad70bdb884d0f7e8afd67e41134a (patch)
tree376d97d938bc477b25f12c09612d94fbd0bc5eb7 /lib
parent9918ff136c44a1c87822793ffee95a243d8d7d60 (diff)
parentaba3e5b25a349f8b4ffc3af859e31cb83314ac9e (diff)
Merge branch 'quilt/rr'
Conflicts: arch/x86/kernel/setup.c
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig11
-rw-r--r--lib/Makefile1
-rw-r--r--lib/find_next_bit.c31
-rw-r--r--lib/is_single_threaded.c45
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;
+}