Example #1
0
static int
list_ensure_space( list *a )
{
	int status = LIST_OK;
	if ( a->max==0 )
		status = list_alloc( a );
	else if ( a->n >= a->max )
		status = list_realloc( a );
	return status;
}
Example #2
0
File: list.c Project: gobics/uproc
int uproc_list_pop(uproc_list *list, void *value)
{
    if (list->size < 1) {
        return uproc_error_msg(UPROC_EINVAL, "pop from empty list");
    }
    uproc_list_get(list, list->size - 1, value);
    list->size--;
    if (list->size > list->capacity / 4) {
        return 0;
    }
    return list_realloc(list, list->capacity / 2);
}
Example #3
0
File: obj.c Project: jxy859/nvml
/*
 * obj_realloc_root -- (internal) reallocate root object
 */
static int
obj_realloc_root(PMEMobjpool *pop, struct object_store *store, size_t size,
	size_t old_size,
	void (*constructor)(PMEMobjpool *pop, void *ptr, void *arg), void *arg)
{
	LOG(3, "pop %p store %p size %zu old_size %zu",
		pop, store, size, old_size);

	struct list_head *lhead = &store->root.head;
	uint64_t size_offset = OOB_OFFSET_OF(lhead->pe_first, size);
	struct carg_realloc carg;

	carg.ptr = OBJ_OFF_TO_PTR(pop, lhead->pe_first.off);
	carg.old_size = old_size;
	carg.new_size = size;
	carg.user_type = POBJ_ROOT_TYPE_NUM;
	carg.constructor = constructor;
	carg.arg = arg;

	return list_realloc(pop, lhead, 0, NULL, size,
				constructor_zrealloc_root, &carg,
				size_offset, size, &lhead->pe_first);
}
Example #4
0
File: list.c Project: gobics/uproc
uproc_list *uproc_list_create(size_t value_size)
{
    struct uproc_list_s *list;
    if (!value_size) {
        uproc_error_msg(UPROC_EINVAL, "value size must be non-zero");
        return NULL;
    }

    list = malloc(sizeof *list);
    if (!list) {
        uproc_error(UPROC_ENOMEM);
        return NULL;
    }
    list->size = list->capacity = 0;
    list->value_size = value_size;
    list->data = NULL;

    if (list_realloc(list, 0)) {
        free(list);
        return NULL;
    }
    return list;
}
Example #5
0
File: list.c Project: gobics/uproc
/* Doubles the capacity of a list. If (value_size * capacity) would exceed
 * MAX_SIZE, use (MAX_SIZE / value_size) instead of doubling.
 * Fails if the size is already (MAX_SIZE / value_size).  */
static int list_grow(struct uproc_list_s *list, long n)
{
    long cap_req, cap_new, cap_max;

    cap_req = list->size + n;
    if (cap_req < list->capacity) {
        return 0;
    }

    cap_max = MAX_SIZE / list->value_size;
    if (list->capacity == cap_max || cap_req > cap_max) {
        return uproc_error_msg(UPROC_EINVAL, "list too big");
    }

    if (cap_max / 2 > list->capacity) {
        cap_new = list->capacity * 2;
    } else {
        cap_new = cap_max;
    }
    if (cap_new < cap_req) {
        cap_new = cap_req;
    }
    return list_realloc(list, cap_new);
}
Example #6
0
File: obj.c Project: jxy859/nvml
/*
 * obj_realloc_common -- (internal) common routine for resizing
 *                          existing objects
 */
static int
obj_realloc_common(PMEMobjpool *pop, struct object_store *store,
	PMEMoid *oidp, size_t size, unsigned int type_num,
	void (*constr_alloc)(PMEMobjpool *pop, void *ptr, void *arg),
	void (*constr_realloc)(PMEMobjpool *pop, void *ptr, void *arg))
{

	/* if OID is NULL just allocate memory */
	if (OBJ_OID_IS_NULL(*oidp)) {
		struct carg_alloc carg;
		carg.size = size;

		/* if size is 0 - do nothing */
		if (size == 0)
			return 0;

		return obj_alloc_construct(pop, oidp, size, type_num,
						constr_alloc, &carg);
	}

	if (size > PMEMOBJ_MAX_ALLOC_SIZE) {
		ERR("requested size too large");
		errno = ENOMEM;
		return -1;
	}

	/* if size is 0 just free */
	if (size == 0) {
		obj_free(pop, oidp);
		return 0;
	}

	struct carg_realloc carg;
	carg.ptr = OBJ_OFF_TO_PTR(pop, oidp->off);
	carg.new_size = size;
	carg.old_size = pmemobj_alloc_usable_size(*oidp);
	carg.user_type = type_num;
	carg.constructor = NULL;
	carg.arg = NULL;

	struct oob_header *pobj = OOB_HEADER_FROM_OID(pop, *oidp);
	uint16_t user_type_old = pobj->data.user_type;

	ASSERT(user_type_old < PMEMOBJ_NUM_OID_TYPES);

	if (type_num >= PMEMOBJ_NUM_OID_TYPES) {
		errno = EINVAL;
		ERR("!obj_realloc_construct");
		LOG(2, "type_num has to be in range [0, %u]",
		    PMEMOBJ_NUM_OID_TYPES - 1);
		return -1;
	}

	struct list_head *lhead_old = &store->bytype[user_type_old].head;
	if (type_num == user_type_old) {
		int ret = list_realloc(pop, lhead_old, 0, NULL, size,
				constr_realloc, &carg, 0, 0, oidp);
		if (ret)
			LOG(2, "list_realloc failed");

		return ret;
	} else {
		struct list_head *lhead_new = &store->bytype[type_num].head;

		/*
		 * Redo log updates 8 byte entries, so we have to prepare
		 * full 8-byte value even if we want to update smaller field
		 * (here: user_type).
		 */
		struct oob_header_data d = pobj->data;
		d.user_type = type_num;

		uint64_t data_offset = OOB_OFFSET_OF(*oidp, data);

		int ret = list_realloc_move(pop, lhead_old, lhead_new, 0, NULL,
				size, constr_realloc, &carg, data_offset,
				*((uint64_t *)&d), oidp);
		if (ret)
			LOG(2, "list_realloc_move failed");

		return ret;
	}
}
Example #7
0
/*
 * obj_realloc_common -- (internal) common routine for resizing
 *                          existing objects
 */
static int
obj_realloc_common(PMEMobjpool *pop, struct object_store *store,
	PMEMoid *oidp, size_t size, type_num_t type_num, int zero_init)
{

	/* if OID is NULL just allocate memory */
	if (OBJ_OID_IS_NULL(*oidp)) {
		/* if size is 0 - do nothing */
		if (size == 0)
			return 0;

		return obj_alloc_construct(pop, oidp, size, type_num,
				zero_init, NULL, NULL);
	}

	if (size > PMEMOBJ_MAX_ALLOC_SIZE) {
		ERR("requested size too large");
		errno = ENOMEM;
		return -1;
	}

	/* if size is 0 just free */
	if (size == 0) {
		obj_free(pop, oidp);
		return 0;
	}

	struct carg_realloc carg;
	carg.ptr = OBJ_OFF_TO_PTR(pop, oidp->off);
	carg.new_size = size;
	carg.old_size = pmemobj_alloc_usable_size(*oidp);
	carg.user_type = type_num;
	carg.constructor = NULL;
	carg.arg = NULL;
	carg.zero_init = zero_init;

	struct oob_header *pobj = OOB_HEADER_FROM_OID(pop, *oidp);
	type_num_t user_type_old = pobj->data.user_type;

	/* callers should have checked this */
	ASSERT(type_num < PMEMOBJ_NUM_OID_TYPES);
	ASSERT(user_type_old < PMEMOBJ_NUM_OID_TYPES);

	struct list_head *lhead_old = &store->bytype[user_type_old].head;
	if (type_num == user_type_old) {
		int ret = list_realloc(pop, lhead_old, 0, NULL, size,
				constructor_realloc, &carg, 0, 0, oidp);
		if (ret)
			LOG(2, "list_realloc failed");

		/* oidp could be different, so we need to get the ptr again */
		VALGRIND_DO_MAKE_MEM_NOACCESS(pop,
			&OOB_HEADER_FROM_OID(pop, *oidp)->data.padding,
			sizeof (OOB_HEADER_FROM_OID(pop, *oidp)->data.padding));

		return ret;
	} else {
		struct list_head *lhead_new = &store->bytype[type_num].head;

		/*
		 * Header padding doubles as a red zone to check for header
		 * overwrites. Disable it temporarily so we can modify the type
		 * number.
		 */
		VALGRIND_DO_MAKE_MEM_DEFINED(pop,
			&OOB_HEADER_FROM_OID(pop, *oidp)->data.padding,
			sizeof (OOB_HEADER_FROM_OID(pop, *oidp)->data.padding));

		/*
		 * Redo log updates 8 byte entries, so we have to prepare
		 * full 8-byte value even if we want to update smaller field
		 * (here: user_type).
		 */
		struct oob_header_data d = pobj->data;
		d.user_type = type_num;

		uint64_t data_offset = OOB_OFFSET_OF(*oidp, data);

		int ret = list_realloc_move(pop, lhead_old, lhead_new, 0, NULL,
				size, constructor_realloc, &carg, data_offset,
				*((uint64_t *)&d), oidp);
		if (ret)
			LOG(2, "list_realloc_move failed");

		/* oidp could be different, so we need to get the ptr again */
		VALGRIND_DO_MAKE_MEM_NOACCESS(pop,
			&OOB_HEADER_FROM_OID(pop, *oidp)->data.padding,
			sizeof (OOB_HEADER_FROM_OID(pop, *oidp)->data.padding));

		return ret;
	}
}