/*
* call-seq:
* Raindrops.new(size) -> raindrops object
*
* Initializes a Raindrops object to hold +size+ counters. +size+ is
* only a hint and the actual number of counters the object has is
* dependent on the CPU model, number of cores, and page size of
* the machine. The actual size of the object will always be equal
* or greater than the specified +size+.
*/
static VALUE init(VALUE self, VALUE size)
{
struct raindrops *r = DATA_PTR(self);
int tries = 1;
size_t tmp;
if (r->drops != MAP_FAILED)
rb_raise(rb_eRuntimeError, "already initialized");
r->size = NUM2SIZET(size);
if (r->size < 1)
rb_raise(rb_eArgError, "size must be >= 1");
tmp = PAGE_ALIGN(raindrop_size * r->size);
r->capa = tmp / raindrop_size;
assert(PAGE_ALIGN(raindrop_size * r->capa) == tmp && "not aligned");
retry:
r->drops = mmap(NULL, tmp,
PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
if (r->drops == MAP_FAILED) {
if ((errno == EAGAIN || errno == ENOMEM) && tries-- > 0) {
rb_gc();
goto retry;
}
rb_sys_fail("mmap");
}
r->pid = getpid();
return self;
}