mirror of /home/gitosis/repositories/libowfat.git
Mirror of :pserver:cvs@cvs.fefe.de:/cvs libowfat
https://www.fefe.de/libowfat/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
47 lines
1.7 KiB
47 lines
1.7 KiB
#include "likely.h" |
|
#include <stdlib.h> |
|
#include "iarray.h" |
|
|
|
void* iarray_allocate(iarray* ia,size_t pos) { |
|
size_t y; |
|
/* first the easy case without locking */ |
|
if (__likely((y=pos/ia->elemperpage) < ia->pagefence && ia->pages[y])) |
|
return ia->pages[y]+(pos%ia->elemperpage)*ia->elemsize; |
|
/* the case where ia->pages == NULL is implicit */ |
|
|
|
pthread_mutex_lock(&ia->m); |
|
|
|
if (__unlikely(y >= ia->pagefence)) { |
|
char** np; |
|
/* The data structure is an array of pointer to pages. |
|
* Each page holds at least one element of the array. |
|
* Here we realloc the array of pointers. Each element in this |
|
* array is only 4 or 8 bytes, so we should allocate a few more than |
|
* we need to cut down on future reallocs. */ |
|
size_t z=(y+512)&-512; /* round up to multiple of 512 */ |
|
/* It may seem as if there can be no integer overflow in the |
|
* indirect index, because then the array would not fit into the |
|
* address space in the first place, but remember that this is a |
|
* sparse array. Someone might just pass in an unreasonable large |
|
* index and have large elements, too */ |
|
if (z==0) goto unlockandfail; /* integer overflow */ |
|
np=realloc(ia->pages,z*ia->bytesperpage); |
|
if (!np) goto unlockandfail; |
|
ia->pagefence=z; |
|
ia->pages=np; |
|
} |
|
|
|
/* at this point we know the slot exists */ |
|
/* through a race between the early-out above and the |
|
* pthread_mutex_lock, the page pointer to it could be non-NULL, |
|
* however */ |
|
if (__unlikely(ia->pages[y]==0 && (ia->pages[y]=malloc(ia->bytesperpage))==0)) { |
|
unlockandfail: |
|
pthread_mutex_unlock(&ia->m); |
|
return 0; |
|
} |
|
|
|
pthread_mutex_unlock(&ia->m); |
|
|
|
return ia->pages[y] + (pos%ia->elemperpage)*ia->elemsize; |
|
}
|
|
|