linux-more-osi-sleep-wakeup-fun-20020624

"the attached patch 'fixes', in my opinion, in osi_alloc.  objects <=
AFS_SMALLOCSIZ are alloced with kmalloc, other vmalloc.  if kmalloc
fails it doesnt fail over to vmalloc.  TASK_RUNNING is set after
schedule.  it doesnt drop the GLOCK.  i moved the allocator init
later so that it doesnt need to toggle the semaphore just before
going to linux_alloc."
This commit is contained in:
Chas Williams 2002-06-24 16:40:41 +00:00 committed by Derrick Brashear
parent 60659d2c8f
commit fe1648ca02

View File

@ -24,7 +24,7 @@ RCSID("$Header$");
#include "../afs/afs_atomlist.h" #include "../afs/afs_atomlist.h"
#include "../afs/afs_lhash.h" #include "../afs/afs_lhash.h"
#define MAX_KMALLOC_SIZE (131072-16) /* Max we can alloc in physmem */ #define MAX_KMALLOC_SIZE AFS_SMALLOCSIZ /* Max we should alloc with kmalloc */
#define MAX_BUCKET_LEN 30 /* max. no. of entries per buckets we expect to see */ #define MAX_BUCKET_LEN 30 /* max. no. of entries per buckets we expect to see */
#define STAT_INTERVAL 8192 /* we collect stats once every STAT_INTERVAL allocs*/ #define STAT_INTERVAL 8192 /* we collect stats once every STAT_INTERVAL allocs*/
@ -79,14 +79,12 @@ static int hash_equal(const void *a, const void *b)
static void *linux_alloc(unsigned int asize) static void *linux_alloc(unsigned int asize)
{ {
void *new = NULL; void *new = NULL;
int has_afs_glock = ISAFS_GLOCK(); int max_retry = 10;
/* if global lock has been held save this info and unlock it. */
if (has_afs_glock)
AFS_GUNLOCK();
/* if we can use kmalloc use it to allocate the required memory. */ /* if we can use kmalloc use it to allocate the required memory. */
if (asize < MAX_KMALLOC_SIZE) { while(!new && max_retry)
{
if (asize <= MAX_KMALLOC_SIZE) {
new = (void *)(unsigned long)kmalloc(asize, new = (void *)(unsigned long)kmalloc(asize,
#ifdef GFP_NOFS #ifdef GFP_NOFS
GFP_NOFS GFP_NOFS
@ -96,30 +94,30 @@ static void *linux_alloc(unsigned int asize)
); );
if (new) /* piggy back alloc type */ if (new) /* piggy back alloc type */
(unsigned long)new |= KM_TYPE; (unsigned long)new |= KM_TYPE;
} } else {
if (!new) { /* otherwise use vmalloc */ new = (void *)vmalloc(asize);
int max_wait = 10; if (new) /* piggy back alloc type */
while (!(new = (void *)vmalloc(asize))) { (unsigned long)new |= VM_TYPE;
if (--max_wait <=0) {
break;
} }
if (!new) {
#ifdef set_current_state #ifdef set_current_state
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
#else #else
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
#endif #endif
schedule_timeout(HZ); schedule_timeout(HZ);
#ifdef set_current_state
set_current_state(TASK_RUNNING);
#else
current->state = TASK_RUNNING;
#endif
--max_retry;
} }
if (new) /* piggy back alloc type */
(unsigned long)new |= VM_TYPE;
} }
if (new) if (new)
memset(MEMADDR(new), 0, asize); memset(MEMADDR(new), 0, asize);
/* if the global lock had been held, lock it again. */
if (has_afs_glock)
AFS_GLOCK();
return new; return new;
} }
@ -287,22 +285,22 @@ void *osi_linux_alloc(unsigned int asize)
void *new = NULL; void *new = NULL;
struct osi_linux_mem *lmem; struct osi_linux_mem *lmem;
new = linux_alloc(asize); /* get a chunk of memory of size asize */
if (!new) {
printf("afs_osi_Alloc: Can't vmalloc %d bytes.\n", asize);
return new;
}
down(&afs_linux_alloc_sem); down(&afs_linux_alloc_sem);
if (allocator_init == 0) { /* allocator hasn't been initialized yet */ /* allocator hasn't been initialized yet */
if (allocator_init == 0) {
if (linux_alloc_init() == 0) { if (linux_alloc_init() == 0) {
goto error; goto error;
} }
allocator_init = 1; /* initialization complete */ allocator_init = 1; /* initialization complete */
} }
up(&afs_linux_alloc_sem);
new = linux_alloc(asize); /* get a chunk of memory of size asize */
down(&afs_linux_alloc_sem);
if (!new) {
printf("afs_osi_Alloc: Can't vmalloc %d bytes.\n", asize);
goto error;
}
/* get an atom to store the pointer to the chunk */ /* get an atom to store the pointer to the chunk */
lmem = (struct osi_linux_mem *)afs_atomlist_get(al_mem_pool); lmem = (struct osi_linux_mem *)afs_atomlist_get(al_mem_pool);