Ejemplo n.º 1
0
static void do_event_loop(int timeout, bool sort_with_prio)
{
	int i, nr;

refresh:
	event_loop_refresh = false;
	nr = epoll_wait(efd, events, nr_events, timeout);
	if (sort_with_prio)
		xqsort(events, nr, epoll_event_cmp);

	if (nr < 0) {
		if (errno == EINTR)
			return;
		sd_err("epoll_wait failed: %m");
		exit(1);
	} else if (nr) {
		for (i = 0; i < nr; i++) {
			struct event_info *ei;

			ei = (struct event_info *)events[i].data.ptr;
			ei->handler(ei->fd, events[i].events, ei->data);

			if (event_loop_refresh)
				goto refresh;
		}
	}
}
Ejemplo n.º 2
0
static void
vsort_xqsort(struct vsort_timing *vt, size_t loops)
{
	size_t n = loops;

	while (n-- > 0) {
		memcpy(vt->copy, vt->data, vt->len);
		xqsort(vt->copy, vt->items, vt->isize, vsort_long_cmp);
	}
}
Ejemplo n.º 3
0
void xqsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *))
{
	char  *i;
	char *lo, *hi;
	char *last,*mid;
	size_t size,lsize,rsize;

	if (nel < 2 || width == 0)
		return;

	
	lo = base; 
	hi = (char *)base + (nel - 1)*width;
	
	size = (hi - lo) / width + 1;  /* number of elements to sort */ 

	mid = lo + (size / 2) * width;      /* find middle element */  
	
	swap(lo,mid,width);
	last = lo;
	i = base + width;
        while( i <= hi )
        {
                if (compar(lo,i) > 0)
		{
			last = last + width;
			swap(i,last,width);
		}	
		i = i + width;
        }
	
	swap(lo,last,width);
	lsize = (last - lo) / width ;  /* number of left elements  */ 
	rsize = (hi - last) / width ;  /* number of right elements  */ 
	xqsort(lo,lsize ,width,compar);
	xqsort(last + width,rsize ,width,compar);		

	return;
}
Ejemplo n.º 4
0
// vuniq sorts the vector and then discards duplicates,
// in the manner of sort | uniq.
void
vuniq(Vec *v)
{
	int i, n;

	xqsort(v->p, v->len, sizeof(v->p[0]), strpcmp);
	n = 0;
	for(i=0; i<v->len; i++) {
		if(n>0 && streq(v->p[i], v->p[n-1]))
			xfree(v->p[i]);
		else
			v->p[n++] = v->p[i];
	}
	v->len = n;
}
Ejemplo n.º 5
0
/**
 * Dump the links sorted by decreasing leak size.
 */
G_GNUC_COLD void
leak_dump(const leak_set_t *ls)
{
	int count;
	struct filler filler;
	int i;

	leak_set_check(ls);

	count = htable_count(ls->stacks);

	if (count == 0)
		goto leaks_by_place;

	/*
	 * Linearize hash table into an array before sorting it by
	 * decreasing leak size.
	 */

	filler.leaks = xpmalloc(sizeof(struct leak) * count);
	filler.count = count;
	filler.idx = 0;
	filler.kt = LEAK_KEY_STACK;

	htable_foreach(ls->stacks, fill_array, &filler);
	xqsort(filler.leaks, count, sizeof(struct leak), leak_size_cmp);

	/*
	 * Dump the leaks by allocation place.
	 */

	g_warning("leak summary by stackframe and total decreasing size:");
	g_warning("distinct calling stacks found: %d", count);

	for (i = 0; i < count; i++) {
		struct leak *l = &filler.leaks[i];
		size_t avg = l->lr->size / (0 == l->lr->count ? 1 : l->lr->count);
		g_warning("%zu bytes (%zu block%s, average %zu byte%s) from:",
			l->lr->size, l->lr->count, l->lr->count == 1 ? "" : "s",
			avg, 1 == avg ? "" : "s");
		stacktrace_atom_decorate(stderr, l->u.sa,
			STACKTRACE_F_ORIGIN | STACKTRACE_F_SOURCE);
	}

	xfree(filler.leaks);

leaks_by_place:

	count = htable_count(ls->places);

	if (count == 0)
		return;

	/*
	 * Linearize hash table into an array before sorting it by
	 * decreasing leak size.
	 */

	filler.leaks = xpmalloc(sizeof(struct leak) * count);
	filler.count = count;
	filler.idx = 0;
	filler.kt = LEAK_KEY_PLACE;

	htable_foreach(ls->places, fill_array, &filler);
	xqsort(filler.leaks, count, sizeof(struct leak), leak_size_cmp);

	/*
	 * Dump the leaks by allocation place.
	 */

	g_warning("leak summary by origin and total decreasing size:");
	g_warning("distinct allocation points found: %d", count);

	for (i = 0; i < count; i++) {
		struct leak *l = &filler.leaks[i];
		size_t avg = l->lr->size / (0 == l->lr->count ? 1 : l->lr->count);
		g_warning("%zu bytes (%zu block%s, average %zu byte%s) from \"%s\"",
			l->lr->size, l->lr->count, l->lr->count == 1 ? "" : "s",
			avg, 1 == avg ? "" : "s", l->u.place);
	}

	xfree(filler.leaks);
}
Ejemplo n.º 6
0
/*
 * Initialize the data vdi
 *
 * @vid: the vdi where the allocator resides
 */
int oalloc_init(uint32_t vid)
{
	struct strbuf buf = STRBUF_INIT;
	struct sd_inode *inode = xmalloc(sizeof(struct sd_inode));
	struct header hd = {
		.nr_free = 1,
	};
	struct free_desc fd = {
		.start = 1, /* Use first object as the meta object */
		.count = MAX_DATA_OBJS - 1,
	};
	int ret;

	strbuf_add(&buf, &hd, sizeof(hd));
	strbuf_add(&buf, &fd, sizeof(fd));

	ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode,
			     sizeof(*inode), 0);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to read inode, %" PRIx32", %s", vid,
		       sd_strerror(ret));
		goto out;
	}
	ret = sd_write_object(vid_to_data_oid(vid, 0), buf.buf,
			      buf.len, 0, true);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to create meta object for %" PRIx32", %s", vid,
		       sd_strerror(ret));
		goto out;
	}
	sd_inode_set_vid(inode, 0, vid);
	ret = sd_inode_write_vid(inode, 0, vid, vid, 0, false, false);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to update inode, %" PRIx32", %s", vid,
		       sd_strerror(ret));
		goto out;
	}
out:
	strbuf_release(&buf);
	free(inode);
	return ret;
}

/*
 * Allocate the objects and update the free list.
 *
 * Callers are expected to call oalloc_new_finish() to update the inode bitmap
 * after filling up the data.
 *
 * @vid: the vdi where the allocator resides
 * @start: start index of the objects to allocate
 * @count: number of the objects to allocate
 */
int oalloc_new_prepare(uint32_t vid, uint64_t *start, uint64_t count)
{
	char *meta = xvalloc(SD_DATA_OBJ_SIZE);
	struct header *hd;
	struct free_desc *fd;
	uint64_t oid = vid_to_data_oid(vid, 0), i;
	int ret;

	ret = sd_read_object(oid, meta, SD_DATA_OBJ_SIZE, 0);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to read meta %" PRIx64 ", %s", oid,
		       sd_strerror(ret));
		goto out;
	}

	hd = (struct header *)meta;
	fd = (struct free_desc *)(meta + oalloc_meta_length(hd)) - 1;
	sd_debug("used %"PRIu64", nr_free %"PRIu64, hd->used, hd->nr_free);
	for (i = 0; i < hd->nr_free; i++, fd--) {
		sd_debug("start %"PRIu64", count %"PRIu64, fd->start,
			 fd->count);
		if (fd->count > count)
			break;
	}
	if (i == hd->nr_free) {
		ret = SD_RES_NO_SPACE;
		goto out;
	}

	*start = fd->start;
	fd->start += count;
	fd->count -= count;
	hd->used += count;

	/* Update the meta object */
	ret = sd_write_object(oid, meta, oalloc_meta_length(hd), 0, false);
	if (ret != SD_RES_SUCCESS)
		sd_err("failed to update meta %"PRIx64 ", %s", oid,
		       sd_strerror(ret));
out:
	free(meta);
	return ret;
}

/*
 * Update the inode map of the vid
 *
 * @vid: the vdi where the allocator resides
 * @start: start index of the objects to update
 * @count: number of the objects to update
 */
int oalloc_new_finish(uint32_t vid, uint64_t start, uint64_t count)
{
	struct sd_inode *inode = xmalloc(sizeof(struct sd_inode));
	int ret;

	ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode,
			     sizeof(*inode), 0);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to read inode, %" PRIx64 ", %s",
		       vid_to_vdi_oid(vid), sd_strerror(ret));
		goto out;
	}

	sd_debug("start %"PRIu64" end %"PRIu64, start, start + count - 1);
	sd_inode_set_vid_range(inode, start, (start + count - 1), vid);

	ret = sd_inode_write(inode, 0, false, false);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to update inode, %" PRIx64", %s",
		       vid_to_vdi_oid(vid), sd_strerror(ret));
		goto out;
	}
out:
	free(inode);
	return ret;
}

static int free_desc_cmp(struct free_desc *a, struct free_desc *b)
{
	return -intcmp(a->start, b->start);
}

static inline int update_and_merge_free_desc(char *meta, uint64_t start,
					     uint64_t count, uint32_t vid)
{
	struct header *hd = (struct header *)meta;
	struct free_desc *tail, *fd = HEADER_TO_FREE_DESC(hd);
	uint64_t i, j;

	/* Try our best to merge it in place, or append it to tail */
	for (i = 0; i < hd->nr_free; i++) {
		if (start + count == fd->start) {
			fd->start = start;
			fd->count += count;
			break;
		} else if(fd->start + fd->count == start) {
			fd->count +=count;
			break;
		}
		fd++;
	}

	if (i == hd->nr_free) {
		if (hd->nr_free >= MAX_FREE_DESC)
			return SD_RES_NO_SPACE;

		tail = (struct free_desc *)(meta + oalloc_meta_length(hd));
		tail->start = start;
		tail->count = count;
		hd->nr_free++;
	}

	hd->used -= count;
	xqsort(HEADER_TO_FREE_DESC(hd), hd->nr_free, free_desc_cmp);

	/* Merge as hard as we can */
	j = hd->nr_free - 1;
	tail = (struct free_desc *)(meta + oalloc_meta_length(hd)) - 1;
	for (i = 0; i < j; i++, tail--) {
		struct free_desc *front = tail - 1;

		sd_debug("start %"PRIu64", count %"PRIu64, tail->start,
			 tail->count);
		if (tail->start + tail->count > front->start)
			sd_emerg("bad free descriptor found at %"PRIx32, vid);
		if (tail->start + tail->count == front->start) {
			front->start = tail->start;
			front->count += tail->count;
			memmove(tail, tail + 1, sizeof(*tail) * i);
			hd->nr_free--;
		}
	}

	return SD_RES_SUCCESS;
}

/*
 * Discard the allocated objects and update the free list of the allocator
 *
 * Caller should check the return value since it might fail.
 *
 * @vid: the vdi where the allocator resides
 * @start: start index of the objects to free
 * @count: number of the objects to free
 */
int oalloc_free(uint32_t vid, uint64_t start, uint64_t count)
{
	char *meta = xvalloc(SD_DATA_OBJ_SIZE);
	struct header *hd;
	uint64_t oid = vid_to_data_oid(vid, 0), i;
	struct sd_inode *inode = xmalloc(sizeof(struct sd_inode));
	int ret;

	ret = sd_read_object(vid_to_vdi_oid(vid), (char *)inode,
			     sizeof(*inode), 0);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to read inode, %" PRIx64 ", %s",
		       vid_to_vdi_oid(vid), sd_strerror(ret));
		goto out;
	}

	sd_debug("discard start %"PRIu64" end %"PRIu64, start,
		 start + count - 1);
	sd_inode_set_vid_range(inode, start, (start + count - 1), 0);

	ret = sd_inode_write(inode, 0, false, false);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to update inode, %" PRIx64", %s",
		       vid_to_vdi_oid(vid), sd_strerror(ret));
		goto out;
	}

	ret = sd_read_object(oid, meta, SD_DATA_OBJ_SIZE, 0);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to read meta %" PRIx64 ", %s", oid,
		       sd_strerror(ret));
		goto out;
	}

	ret = update_and_merge_free_desc(meta, start, count, vid);
	if (ret != SD_RES_SUCCESS)
		goto out;

	/* XXX use aio to speed up remove of objects */
	for (i = 0; i < count; i++) {
		struct sd_req hdr;
		int res;

		sd_init_req(&hdr, SD_OP_REMOVE_OBJ);
		hdr.obj.oid = vid_to_data_oid(vid, start + i);
		res = exec_local_req(&hdr, NULL);
		/*
		 * return the error code if it does not
		 * success or can't find obj.
		 */
		if (res != SD_RES_SUCCESS && res != SD_RES_NO_OBJ)
			ret = res;
	}

	hd = (struct header *)meta;
	ret = sd_write_object(oid, meta, oalloc_meta_length(hd), 0, false);
	if (ret != SD_RES_SUCCESS) {
		sd_err("failed to update meta %"PRIx64 ", %s", oid,
		       sd_strerror(ret));
		goto out;
	}
	sd_debug("used %"PRIu64", nr_free %"PRIu64, hd->used, hd->nr_free);
out:
	free(meta);
	free(inode);
	return ret;
}
Ejemplo n.º 7
0
/**
 * Check which of qsort(), xqsort(), xsort() or smsort() is best for sorting
 * aligned arrays with a native item size of OPSIZ.  At identical performance
 * level, we prefer our own sorting algorithms instead of libc's qsort() for
 * memory allocation purposes.
 *
 * @param items		amount of items to use in the sorted array
 * @param idx		index of the virtual routine to update
 * @param verbose	whether to be verbose
 * @param which		either "large" or "small", for logging
 */
static void
vsort_init_items(size_t items, unsigned idx, int verbose, const char *which)
{
	struct vsort_testing tests[] = {
		{ vsort_qsort,	qsort,	0.0, 0, "qsort" },
		{ vsort_xqsort,	xqsort,	0.0, 2, "xqsort" },
		{ vsort_xsort,	xsort,	0.0, 1, "xsort" },
		{ vsort_tqsort,	tqsort,	0.0, 1, "tqsort" },
		{ vsort_smsort,	smsort,	0.0, 1, "smsort" },	/* Only for almost sorted */
	};
	size_t len = items * OPSIZ;
	struct vsort_timing vt;
	size_t loops, highest_loops;
	unsigned i;

	g_assert(uint_is_non_negative(idx));
	g_assert(idx < N_ITEMS(vsort_table));

	vt.data = vmm_alloc(len);
	vt.copy = vmm_alloc(len);
	vt.items = items;
	vt.isize = OPSIZ;
	vt.len = len;
	random_bytes(vt.data, len);

	highest_loops = loops = vsort_loops(items);

	/* The -1 below is to avoid benchmarking smsort() for the general case */

retry_random:
	for (i = 0; i < N_ITEMS(tests) - 1; i++) {
		tests[i].v_elapsed = vsort_timeit(tests[i].v_timer, &vt, &loops);

		if (verbose > 1) {
			s_debug("%s() took %.4f secs for %s array (%zu loops)",
				tests[i].v_name, tests[i].v_elapsed * loops, which, loops);
		}

		if (loops != highest_loops) {
			highest_loops = loops;
			/* Redo all the tests if the number of timing loops changes */
			if (i != 0)
				goto retry_random;
		}
	}

	/*
	 * When dealing with a large amount of items, redo the tests twice with
	 * another set of random bytes to make sure we're not hitting a special
	 * ordering case.
	 */

	if (items >= VSORT_ITEMS) {
		unsigned j;

		for (j = 0; j < 2; j++) {
			random_bytes(vt.data, len);

			for (i = 0; i < N_ITEMS(tests) - 1; i++) {
				tests[i].v_elapsed +=
					vsort_timeit(tests[i].v_timer, &vt, &loops);

				if (verbose > 1) {
					s_debug("%s() spent %.6f secs total for %s array",
						tests[i].v_name, tests[i].v_elapsed, which);
				}

				if (loops != highest_loops) {
					highest_loops = loops;
					/* Redo all the tests if the number of loops changes */
					s_info("%s(): restarting %s array tests with %zu loops",
						G_STRFUNC, which, loops);
					goto retry_random;
				}
			}
		}
	}

	xqsort(tests, N_ITEMS(tests) - 1, sizeof tests[0], vsort_testing_cmp);

	vsort_table[idx].v_sort = vsort_routine(tests[0].v_routine, items);

	if (verbose) {
		s_info("vsort() will use %s() for %s arrays",
			vsort_routine_name(tests[0].v_name, items), which);
	}

	/*
	 * Now sort the data, then randomly perturb them by swapping a few items
	 * so that the array is almost sorted.
	 */

	xqsort(vt.data, vt.items, vt.isize, vsort_long_cmp);
	vsort_perturb_sorted_array(vt.data, vt.items, vt.isize);

retry_sorted:
	for (i = 0; i < N_ITEMS(tests); i++) {
		tests[i].v_elapsed = vsort_timeit(tests[i].v_timer, &vt, &loops);

		if (verbose > 1) {
			s_debug("%s() on almost-sorted took %.4f secs "
				"for %s array (%zu loops)",
				tests[i].v_name, tests[i].v_elapsed * loops, which, loops);
		}

		if (loops != highest_loops) {
			highest_loops = loops;
			/* Redo all the tests if the number of timing loops changes */
			if (i != 0)
				goto retry_sorted;
		}
	}

	xqsort(tests, N_ITEMS(tests), sizeof tests[0], vsort_testing_cmp);

	vsort_table[idx].v_sort_almost = vsort_routine(tests[0].v_routine, items);

	if (verbose) {
		s_info("vsort_almost() will use %s() for %s arrays",
			vsort_routine_name(tests[0].v_name, items), which);
	}

	vmm_free(vt.data, len);
	vmm_free(vt.copy, len);
}
Ejemplo n.º 8
0
int sort(int argc ,char * argv[])
{
	FILE *fp;
	char *lineptr[MAXLINES];  /* pointers to text lines */
	char *tmp;
	int i = 0;
	int j = 0;
	int lines = 0;
	char buf[256];
	char sort_type[3];

	if( argc == 2)
		strcpy(sort_type,"-o");
	else
		strcpy(sort_type,argv[2]);


	fp = fopen(argv[1],"a+");

	if ( NULL  == fp)
	{
		printf("File does not exists\n");
		return -1;
	}

	while( fgets(buf,256,fp))
	{
		tmp = (char *)malloc(strlen(buf)*sizeof(char));
		strcpy(tmp,buf);
		lineptr[lines] = tmp;
		lines++;
	}

	for ( i = 0; i<sizeof(sort_op)/sizeof(sort_op[0]);i++)
        {
                if ( strcmp(sort_type,sort_op[i].type) == 0)
                {
			printf("type is %s\n",sort_op[i].type);
                        pfsort = sort_op[i].pf;
			xqsort(lineptr, lines, sizeof(char *), pfsort); 
                        break;
                }
        }






	fputs("--- after sort --- \n",fp);
	while(lines)
	{
		fputs(lineptr[j],fp);
		lines--;
		j++;
	} 

	fclose(fp);
	return 0;
	
	
}