Esempio n. 1
0
static ph_result_t do_register(ph_hook_point_t *hp, ph_hook_func func,
    void *closure, int8_t pri, ph_hook_unreg_func unreg)
{
  ph_hook_point_head_t *old_head, *new_head;
  ph_result_t res = PH_ERR;
  uint16_t num_items = 0;

  ck_rwlock_write_lock(&rwlock);
  {
    old_head = hp->head;

    if (old_head) {
      num_items = old_head->nitems;
    }

    // num_items is 1-less than the number we want, but the head struct
    // has 1 element embedded, so we're fine to multiply it out here
    new_head = ph_mem_alloc_size(mt.head,
        sizeof(*new_head) + (sizeof(ph_hook_item_t) * (num_items)));

    if (!new_head) {
      goto done;
    }

    new_head->nitems = num_items + 1;

    // Copy old data in
    if (old_head) {
      memcpy(new_head->items, old_head->items,
          old_head->nitems * sizeof(ph_hook_item_t));
    }

    new_head->items[num_items].closure = closure;
    new_head->items[num_items].func = func;
    new_head->items[num_items].pri = pri;
    new_head->items[num_items].unreg = unreg;

    qsort(new_head->items, new_head->nitems,
        sizeof(ph_hook_item_t), compare_item);

    hp->head = new_head;

    if (old_head) {
      ph_thread_epoch_defer(&old_head->entry, free_head);
    }

    res = PH_OK;
  }
done:
  ck_rwlock_write_unlock(&rwlock);

  return res;
}
Esempio n. 2
0
char *ph_mem_strdup(ph_memtype_t memtype, const char *str)
{
  uint32_t len = strlen(str) + 1;
  char *d;

  d = ph_mem_alloc_size(memtype, len);
  if (!d) {
    return NULL;
  }

  memcpy(d, str, len);
  return d;
}
Esempio n. 3
0
static struct ph_dns_query_response *make_aaaa_resp(unsigned char *abuf, int alen)
{
  int ancount = DNS_HEADER_ANCOUNT(abuf);
  struct ph_dns_query_response *resp;
  uint32_t size;
  struct ares_addr6ttl *ttls = NULL;
  int res;
  struct hostent *host;
  int nttls;
  int i;
  char *name;

  ttls = malloc(ancount * sizeof(*ttls));
  if (!ttls) {
    return NULL;
  }
  nttls = ancount;

  res = ares_parse_aaaa_reply(abuf, alen, &host, ttls, &nttls);
  if (res) {
    free(ttls);
    return NULL;
  }

  size = sizeof(*resp) + ((nttls - 1) * sizeof(resp->answer[0]));
  resp = ph_mem_alloc_size(mt.aresp, size + strlen(host->h_name) + 1);
  if (!resp) {
    free(ttls);
    return NULL;
  }
  // this is where we'll stash the name
  name = ((char*)resp) + size;
  strcpy(name, host->h_name);

  resp->num_answers = ancount;
  resp->name = name;

  for (i = 0; i < nttls; i++) {
    resp->answer[i].name = name;
    resp->answer[i].ttl = ttls[i].ttl;
    resp->answer[i].addr.family = AF_INET6;
    resp->answer[i].addr.sa.v6.sin6_family = AF_INET6;
    memcpy(&resp->answer[i].addr.sa.v6.sin6_addr, &ttls[i].ip6addr, sizeof(ttls[i].ip6addr));
  }

  free(ttls);
  ares_free_hostent(host);

  return resp;
}
Esempio n. 4
0
ph_string_t *ph_string_make_empty(ph_memtype_t mt,
    uint32_t size)
{
  char *buf = ph_mem_alloc_size(mt, size);
  ph_string_t *str;

  if (!buf) {
    return NULL;
  }

  str = ph_string_make_claim(mt, buf, 0, size);
  if (!str) {
    ph_mem_free(mt, buf);
  }

  return str;
}
Esempio n. 5
0
ph_result_t ph_string_append_buf(ph_string_t *str,
    const char *buf, uint32_t len)
{
  if (len + str->len > str->alloc) {
    // Not enough room
    if (str->mt == PH_STRING_STATIC) {
      // Just clamp to the available space
      len = str->alloc - str->len;
    } else {
      // Grow it
      uint32_t nsize = ph_power_2(str->len + len);
      char *nbuf;

      // Negative memtypes encode the desired memtype as the negative
      // value.  Allocate a buffer from scratch using the desired memtype
      if (str->mt < 0) {
        nbuf = ph_mem_alloc_size(-str->mt, nsize);
      } else {
        nbuf = ph_mem_realloc(str->mt, str->buf, nsize);
      }

      if (nbuf == NULL) {
        return PH_NOMEM;
      }

      if (str->mt < 0) {
        // Promote from static growable to heap allocated growable
        memcpy(nbuf, str->buf, str->len);
        str->mt = -str->mt;
      }

      str->buf = nbuf;
      str->alloc = nsize;
    }
  }

  memcpy(str->buf + str->len, buf, len);
  str->len += len;
  return PH_OK;
}
Esempio n. 6
0
ph_variant_t *ph_var_array(uint32_t nelems)
{
  ph_variant_t *var;

  var = ph_mem_alloc(mt.var);
  if (!var) {
    return NULL;
  }

  var->ref = 1;
  var->type = PH_VAR_ARRAY;
  var->u.aval.len = 0;
  var->u.aval.alloc = nelems;
  var->u.aval.arr = ph_mem_alloc_size(mt.arr, nelems * sizeof(ph_variant_t*));

  if (!var->u.aval.arr) {
    ph_mem_free(mt.var, var);
    return NULL;
  }

  return var;
}
Esempio n. 7
0
static struct ph_dns_query_response *make_srv_resp(unsigned char *abuf, int alen)
{
  struct ph_dns_query_response *resp;
  uint32_t size;
  struct ares_srv_reply *srv, *tmp;
  uint32_t nres = 0, i;

  if (ares_parse_srv_reply(abuf, alen, &srv) != ARES_SUCCESS) {
    return NULL;
  }

  for (nres = 0, tmp = srv; tmp; tmp = tmp->next) {
    nres++;
  }

  size = sizeof(*resp) + ((nres - 1) * sizeof(resp->answer[0]));
  resp = ph_mem_alloc_size(mt.aresp, size);
  if (!resp) {
    ares_free_data(srv);
    return NULL;
  }

  resp->num_answers = nres;

  for (tmp = srv, i = 0; tmp; tmp = tmp->next, i++) {
    resp->answer[i].name = ph_mem_strdup(mt.string, tmp->host);
    resp->answer[i].priority = tmp->priority;
    resp->answer[i].weight = tmp->weight;
    resp->answer[i].port = tmp->port;
  }

  // Sort in priority order
  qsort(resp->answer, nres, sizeof(resp->answer[0]), compare_mx_ent);

  ares_free_data(srv);

  return resp;
}
Esempio n. 8
0
void *ph_mem_realloc(ph_memtype_t mt, void *ptr, uint64_t size)
{
  struct mem_type *mem_type;
  ph_counter_block_t *block;
  static const uint8_t slots[2] = { SLOT_BYTES, SLOT_REALLOC };
  int64_t values[3];
  struct sized_header *hdr;
  uint64_t orig_size;
  void *new_ptr;

  if (size == 0) {
    ph_mem_free(mt, ptr);
    return NULL;
  }
  if (ptr == NULL) {
    return ph_mem_alloc_size(mt, size);
  }
  mem_type = resolve_mt(mt);
  if (mem_type->def.item_size) {
    memory_panic(
      "mem_type %s is not vsize and cannot be used with ph_mem_realloc",
      mem_type->def.name);
    return NULL;
  }

  hdr = ptr;
  hdr--;
  ptr = hdr;

  if (hdr->mt != mt) {
    memory_panic("ph_mem_realloc: hdr->mt %d != caller provided mt %d %s",
      hdr->mt, mt, mem_type->def.name);
  }

  orig_size = hdr->size;
  if (orig_size == size) {
    return ptr;
  }

  hdr = realloc(ptr, size + HEADER_RESERVATION);
  if (!hdr) {
    ph_counter_scope_add(mem_type->scope,
        mem_type->first_slot + SLOT_OOM, 1);

    if (mem_type->def.flags & PH_MEM_FLAGS_PANIC) {
      ph_panic("OOM while allocating %" PRIu64 " bytes of %s/%s memory",
          size + HEADER_RESERVATION, mem_type->def.facility,
          mem_type->def.name);
    }

    return NULL;
  }
  new_ptr = hdr + 1;
  hdr->size = size;

  block = ph_counter_block_open(mem_type->scope);
  values[0] = size - orig_size;
  values[1] = 1;
  ph_counter_block_bulk_add(block, 2, slots, values);
  ph_counter_block_delref(block);

  if (size > orig_size && mem_type->def.flags & PH_MEM_FLAGS_ZERO) {
    memset((char*)new_ptr + orig_size, 0, size - orig_size);
  }

  return new_ptr;
}
Esempio n. 9
0
static ph_result_t do_unregister(ph_hook_point_t *hp, ph_hook_func func,
    void *closure)
{
  ph_hook_point_head_t *old_head, *new_head;
  ph_result_t res = PH_ERR;
  uint16_t off = 0;
  bool found = false;
  struct ph_hook_item_free *unreg = 0;

  ck_rwlock_write_lock(&rwlock);
  {
    old_head = hp->head;

    if (!old_head) {
      goto done;
    }

    for (off = 0; off < old_head->nitems; off++) {
      if (old_head->items[off].func == func &&
          old_head->items[off].closure == closure) {
        found = true;
        break;
      }
    }

    if (!found) {
      goto done;
    }

    new_head = ph_mem_alloc_size(mt.head,
        sizeof(*new_head) + (sizeof(ph_hook_item_t) * (old_head->nitems-1)));

    if (!new_head) {
      goto done;
    }

    if (old_head->items[off].unreg) {
      unreg = ph_mem_alloc(mt.unreg);
      if (!unreg) {
        ph_mem_free(mt.head, new_head);
        goto done;
      }

      unreg->closure = old_head->items[off].closure;
      unreg->func = old_head->items[off].func;
      unreg->unreg = old_head->items[off].unreg;
    }

    new_head->nitems = old_head->nitems - 1;

    // Copy before the item
    if (off) {
      memcpy(new_head->items, old_head->items, off * sizeof(ph_hook_item_t));
    }
    // Copy after the item
    if (off + 1 <= old_head->nitems) {
      memcpy(new_head->items + off, old_head->items + off + 1,
          (old_head->nitems - (off+1)) * sizeof(ph_hook_item_t));
    }

    // Don't need to re-sort, since we simply removed that item

    hp->head = new_head;
    ph_thread_epoch_defer(&old_head->entry, free_head);

    // Arrange to unregister
    if (unreg) {
      ph_thread_epoch_defer(&unreg->entry, call_unreg);
    }

    res = PH_OK;
  }
done:
  ck_rwlock_write_unlock(&rwlock);

  return res;
}