static inline void *kmalloc(size_t size, gfp_t flags)
{
- unsigned i = 0;
+ unsigned i;
void *p;
- do {
- run_shrinkers(flags, i != 0);
-
+ for (i = 0; i < 10; i++) {
if (size) {
size_t alignment = min(rounddown_pow_of_two(size), (size_t)PAGE_SIZE);
alignment = max(sizeof(void *), alignment);
} else {
p = malloc(0);
}
- if (p && (flags & __GFP_ZERO))
- memset(p, 0, size);
- } while (!p && i++ < 10);
+
+ if (p) {
+ if (flags & __GFP_ZERO)
+ memset(p, 0, size);
+ break;
+ }
+
+ run_shrinkers(flags, true);
+ }
return p;
}
static inline struct page *alloc_pages(gfp_t flags, unsigned int order)
{
size_t size = PAGE_SIZE << order;
- unsigned i = 0;
+ unsigned i;
void *p;
- do {
- run_shrinkers(flags, i != 0);
-
+ for (i = 0; i < 10; i++) {
p = aligned_alloc(PAGE_SIZE, size);
- if (p && (flags & __GFP_ZERO))
- memset(p, 0, size);
- } while (!p && i++ < 10);
+
+ if (p) {
+ if (flags & __GFP_ZERO)
+ memset(p, 0, size);
+ break;
+ }
+
+ run_shrinkers(flags, true);
+ }
return p;
}
#define vfree(p) free(p)
-static inline void *__vmalloc(unsigned long size, gfp_t gfp_mask)
+static inline void *__vmalloc(unsigned long size, gfp_t flags)
{
- unsigned i = 0;
+ unsigned i;
void *p;
size = round_up(size, PAGE_SIZE);
- do {
- run_shrinkers(gfp_mask, i != 0);
-
+ for (i = 0; i < 10; i++) {
p = aligned_alloc(PAGE_SIZE, size);
- if (p && gfp_mask & __GFP_ZERO)
- memset(p, 0, size);
- } while (!p && i++ < 10);
+
+ if (p) {
+ if (flags & __GFP_ZERO)
+ memset(p, 0, size);
+ break;
+ }
+
+ run_shrinkers(flags, true);
+ }
return p;
}
#include <stdio.h>
+#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/mutex.h>
}
mutex_unlock(&shrinker_lock);
}
+
+static int shrinker_thread(void *arg)
+{
+ while (!kthread_should_stop()) {
+ sleep(1);
+ run_shrinkers(GFP_KERNEL, false);
+ }
+
+ return 0;
+}
+
+struct task_struct *shrinker_task;
+
+__attribute__((constructor(103)))
+static void shrinker_thread_init(void)
+{
+ shrinker_task = kthread_run(shrinker_thread, NULL, "shrinkers");
+ BUG_ON(IS_ERR(shrinker_task));
+}
+
+__attribute__((destructor(103)))
+static void shrinker_thread_exit(void)
+{
+ int ret = kthread_stop(shrinker_task);
+ BUG_ON(ret);
+
+ shrinker_task = NULL;
+}