diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 74767b24..aabd4386 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -679,4 +679,5 @@ extern int (*linux_clock_gettime)(clockid_t clk_id, struct timespec *tp); extern void terminate_host(int pid, struct thread *thread); struct sig_pending *getsigpending(struct thread *thread, int delflag); int interrupt_from_user(void *regs0); +extern unsigned long shmid_index[]; #endif diff --git a/kernel/shmobj.c b/kernel/shmobj.c index 1abc7b5a..fcfb75bd 100644 --- a/kernel/shmobj.c +++ b/kernel/shmobj.c @@ -225,8 +225,6 @@ int shmobj_create_indexed(struct shmid_ds *ds, struct shmobj **objp) static void shmobj_destroy(struct shmobj *obj) { extern struct shm_info the_shm_info; - extern struct list_head kds_free_list; - extern int the_maxi; struct shmlock_user *user; size_t size; int npages; @@ -306,27 +304,13 @@ static void shmobj_destroy(struct shmobj *obj) kfree(obj); } else { + int i = obj->index / 64; + unsigned long x = 1UL << (obj->index % 64); + list_del(&obj->chain); --the_shm_info.used_ids; - - list_add(&obj->chain, &kds_free_list); - /* For index reuse, release in descending order of index. */ - for (;;) { - struct shmobj *p; - - list_for_each_entry(p, &kds_free_list, chain) { - if (p->index == the_maxi) { - break; - } - } - if (&p->chain == &kds_free_list) { - break; - } - - list_del(&p->chain); - kfree(p); - --the_maxi; - } + shmid_index[i] &= ~x; + kfree(obj); } return; } diff --git a/kernel/syscall.c b/kernel/syscall.c index eb6c9c23..6608ffc2 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -6161,9 +6161,40 @@ struct kshmid_ds { struct list_head chain; }; -int the_maxi = -1; +unsigned long shmid_index[512]; + +static int get_shmid_max_index(void) +{ + int i; + int index = -1; + + for (i = 511; i >= 0; i--) { + if (shmid_index[i]) { + index = i * 64 + 63 - __builtin_clzl(shmid_index[i]); + break; + } + } + return index; +} + +static int get_shmid_index(void) +{ + int index = get_shmid_max_index(); + int i; + unsigned long x; + + for (index = 0;; index++) { + i = index / 64; + x = 1UL << (index % 64); + if (!(shmid_index[i] & x)) { + shmid_index[i] |= x; + break; + } + } + return index; +} + LIST_HEAD(kds_list); -LIST_HEAD(kds_free_list); struct shminfo the_shminfo = { .shmmax = 64L * 1024 * 1024 * 1024, .shmmin = 1, @@ -6384,7 +6415,7 @@ int do_shmget(const key_t key, const size_t size, const int shmflg) return error; } - obj->index = ++the_maxi; + obj->index = get_shmid_index(); list_add(&obj->chain, &kds_list); ++the_shm_info.used_ids; @@ -6670,7 +6701,7 @@ SYSCALL_DECLARE(shmctl) return error; } - maxi = the_maxi; + maxi = get_shmid_max_index(); if (maxi < 0) { maxi = 0; } @@ -6777,7 +6808,7 @@ SYSCALL_DECLARE(shmctl) return error; } - maxi = the_maxi; + maxi = get_shmid_max_index(); if (maxi < 0) { maxi = 0; }