You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
48 lines
1.7 KiB
C
48 lines
1.7 KiB
C
#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;
|
|
}
|