mirror of
https://github.com/torvalds/linux.git
synced 2024-11-05 03:21:32 +00:00
8707d8b8c0
Cause writes to cpuset "cpus" file to update cpus_allowed for member tasks: - collect batches of tasks under tasklist_lock and then call set_cpus_allowed() on them outside the lock (since this can sleep). - add a simple generic priority heap type to allow efficient collection of batches of tasks to be processed without duplicating or missing any tasks in subsequent batches. - make "cpus" file update a no-op if the mask hasn't changed - fix race between update_cpumask() and sched_setaffinity() by making sched_setaffinity() post-check that it's not running on any cpus outside cpuset_cpus_allowed(). [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Paul Menage <menage@google.com> Cc: Paul Jackson <pj@sgi.com> Cc: David Rientjes <rientjes@google.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Cedric Le Goater <clg@fr.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Serge Hallyn <serue@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
71 lines
1.4 KiB
C
71 lines
1.4 KiB
C
/*
|
|
* Simple insertion-only static-sized priority heap containing
|
|
* pointers, based on CLR, chapter 7
|
|
*/
|
|
|
|
#include <linux/slab.h>
|
|
#include <linux/prio_heap.h>
|
|
|
|
int heap_init(struct ptr_heap *heap, size_t size, gfp_t gfp_mask,
|
|
int (*gt)(void *, void *))
|
|
{
|
|
heap->ptrs = kmalloc(size, gfp_mask);
|
|
if (!heap->ptrs)
|
|
return -ENOMEM;
|
|
heap->size = 0;
|
|
heap->max = size / sizeof(void *);
|
|
heap->gt = gt;
|
|
return 0;
|
|
}
|
|
|
|
void heap_free(struct ptr_heap *heap)
|
|
{
|
|
kfree(heap->ptrs);
|
|
}
|
|
|
|
void *heap_insert(struct ptr_heap *heap, void *p)
|
|
{
|
|
void *res;
|
|
void **ptrs = heap->ptrs;
|
|
int pos;
|
|
|
|
if (heap->size < heap->max) {
|
|
/* Heap insertion */
|
|
int pos = heap->size++;
|
|
while (pos > 0 && heap->gt(p, ptrs[(pos-1)/2])) {
|
|
ptrs[pos] = ptrs[(pos-1)/2];
|
|
pos = (pos-1)/2;
|
|
}
|
|
ptrs[pos] = p;
|
|
return NULL;
|
|
}
|
|
|
|
/* The heap is full, so something will have to be dropped */
|
|
|
|
/* If the new pointer is greater than the current max, drop it */
|
|
if (heap->gt(p, ptrs[0]))
|
|
return p;
|
|
|
|
/* Replace the current max and heapify */
|
|
res = ptrs[0];
|
|
ptrs[0] = p;
|
|
pos = 0;
|
|
|
|
while (1) {
|
|
int left = 2 * pos + 1;
|
|
int right = 2 * pos + 2;
|
|
int largest = pos;
|
|
if (left < heap->size && heap->gt(ptrs[left], p))
|
|
largest = left;
|
|
if (right < heap->size && heap->gt(ptrs[right], ptrs[largest]))
|
|
largest = right;
|
|
if (largest == pos)
|
|
break;
|
|
/* Push p down the heap one level and bump one up */
|
|
ptrs[pos] = ptrs[largest];
|
|
ptrs[largest] = p;
|
|
pos = largest;
|
|
}
|
|
return res;
|
|
}
|