Пример #1
0
void kp_final_exit(ktap_state *ks)
{
	if (!list_empty(&G(ks)->probe_events_head) ||
	    !list_empty(&G(ks)->timers))
		kp_wait(ks);

	if (G(ks)->trace_task)
		put_task_struct(G(ks)->trace_task);

	kp_exit_timers(ks);
	kp_probe_exit(ks);

	/* free all resources got by ktap */
	kp_tstring_freeall(ks);
	kp_free_all_gcobject(ks);
	cfunction_cache_exit(ks);

	wait_user_completion(ks);

	kp_transport_exit(ks);

	kp_exitthread(ks);
	kp_free(ks, ks->stack);
	free_all_ci(ks);

	free_kp_percpu_data();

	free_cpumask_var(G(ks)->cpumask);
	kp_free(ks, ks);
}
Пример #2
0
void vector_destroy(vector **v)
{
	bool use_nvm;
	
	if (!v) {
		v_error("got NULL argument unexpectedly; returning\n");
		return;
	}

	if (*v) {
		use_nvm = (*v)->use_nvm;
		(*v)->state = STATE_DEAD;
		kp_flush_range((void *)&((*v)->state), sizeof(ds_state), use_nvm);

		if ((*v)->data) {
			v_debug("testing 0: (*v)->data = %p\n", (*v)->data);
			kp_free((void **)&((*v)->data), use_nvm);  //sets (*v)->data to NULL
#ifdef VECTOR_ASSERT
			v_debug("testing 1: (*v)->data = %p\n", (*v)->data);
			if ((*v)->data != NULL) {
				v_die("kp_free() did not set (*v)->data to NULL as expected!\n");
			}
#endif
		}
		v_debug("testing 2: *v = %p\n", *v);
		kp_free((void **)(v), use_nvm);  //sets *v to NULL after free
#ifdef VECTOR_ASSERT
		v_debug("testing 3: *v = %p\n", *v);
		if (*v != NULL) {
			v_die("kp_free() did not set *v to NULL as expected!\n");
		}
#endif
	}
	v_debug("freed vector's array and vector struct itself\n");
}
Пример #3
0
void kp_obj_free_gclist(ktap_state *ks, ktap_gcobject *o)
{
	while (o) {
		ktap_gcobject *next;

		next = gch(o)->next;
		switch (gch(o)->tt) {
		case KTAP_TYPE_TABLE:
			kp_tab_free(ks, (ktap_tab *)o);
			break;
		case KTAP_TYPE_PROTO:
			free_proto(ks, (ktap_proto *)o);
			break;
		case KTAP_TYPE_UPVAL:
			kp_freeupval(ks, (ktap_upval *)o);
			break;
		case KTAP_TYPE_PTABLE:
			kp_ptab_free(ks, (ktap_ptab *)o);
			break;
		case KTAP_TYPE_RAW:
			kp_free(ks, ((ktap_rawobj *)o)->v);
			break;
		default:
			kp_free(ks, o);
		}
		o = next;
	}
}
Пример #4
0
void kp_table_free(ktap_State *ks, Table *t)
{
	if (t->sizearray > 0)
		kp_free(ks, t->array);
	if (!isdummy(t->node))
		kp_free(ks, t->node);

	kp_free(ks, t);
}
Пример #5
0
int queue_create(queue **q, bool use_nvm) {
#ifdef QUEUE_LOCK
	int ret;
#endif

	if (!q) {
		tp_error("got a NULL argument: q=%p\n", q);
		return -1;
	}
	tp_debug("allocating a new queue\n");

	kp_kpalloc((void **)q, sizeof(queue), use_nvm);
	if (!(*q)) {
		tp_error("malloc(queue) failed\n");
		return -1;
	}

	(*q)->head = NULL;
	(*q)->tail = NULL;
	(*q)->len = 0;
	(*q)->use_nvm = use_nvm;

#ifdef QUEUE_LOCK
	ret = kp_mutex_create("queue lock", &((*q)->lock));
	if (ret != 0) {
		tp_error("mutex creation failed\n");
		kp_free((void **)q, use_nvm);
		return -1;
	};
#endif

	tp_debug("allocated new queue, use_nvm = %s\n", use_nvm ? "true" : "false");
	return 0;
}
Пример #6
0
/* Function to free a task struct. In the hopefully uncommon event that this
 * function is called by queue_destroy() (i.e. the threadpool is destroyed
 * while there are still tasks left in the queue), then it is possible that
 * the task's arg will never be freed and cause a memory leak, because the
 * task_function was never called on the arg. Oh well.
 */
void task_free_fn(void *arg) {
	task *dead_task;
	if (arg) {
		dead_task = (task *)arg;
		kp_free((void **)(&dead_task), dead_task->use_nvm);
	}
}
Пример #7
0
int main(int argc,char *argv[])
{
	KP *kp;
	KP_ARG *arg;
	KP_USER_INFO *user;

	kp=kp_init(argv[1],argv[2],argv[3],argv[4]);
	arg=kp_oauth_arg_init(kp);
	/*
	 * 获取用户信息
	 * 如果成功则返回true
	 * 出错则返回false并设置kp_errno
	 * 如果可能的话kp->errmsg会有错误信息
	 */
	if(kp_get_user_info(kp,arg,&user))
	{
		printf("用户ID:%ld\n",user->user_id);
		printf("用户名:%s\n",user->user_name);
		printf("允许上传最大文件:%ld M\n",user->max_file_size/1024/1024);
		printf("用户空间总量:%ld M\n",user->quota_total/1024/1024);
		printf("用户已使用空间:%ld M\n",user->quota_used/1024/1024);
		printf("回收站空间使用量:%ld M\n",user->quota_recycled/1024/1024);

		//释放内存
		kp_user_info_free(user);
	}
	else
		printf("%s",kp_error(kp->errmsg));

	kp_free(kp);
	kp_arg_destroy(arg);

	return 0;
}
Пример #8
0
void queue_destroy(queue *q) {
	element *head;
	element *next;

	if (!q) {
		tp_error("got a NULL argument: q=%p\n", q);
		return;
	}
	tp_debug("destroying the queue and its elements (if any)\n");

	/* Free the queue's elements, if any: */
	head = q->head;
	while (head) {
#ifdef TP_ASSERT
		if (q->len == 0) {
			tp_die("unexpected: queue length hit 0 while destroying "
					"elements\n");
		}
		if (q->len == 1) {
			if (head != q->tail) {
				tp_die("unexpected: head %p != q->tail %p\n", head, q->tail);
			}
		}
#endif
		next = head->next;
		if (head->free_fn) {
			tp_debug("calling free_fn %p on data %p\n", head->free_fn,
					head->data);
			head->free_fn(head->data);
		}
		kp_free((void **)(&head), q->use_nvm);
		q->len -= 1;
		head = next;
	}

	/* Free the queue itself: */
#ifdef QUEUE_LOCK
	kp_mutex_destroy("queue lock", &(q->lock));
#endif
	kp_free((void **)(&q), q->use_nvm);

	tp_debug("destroyed the queue\n");
}
Пример #9
0
void threadpool_destroy(threadpool *tp, bool wait) {
	if (!tp) {
		tp_error("got a NULL argument: tp=%p\n", tp);
		return;
	}
	tp_debug("destroying thread pool; wait=%s, thread pool currently has "
			"%u workers\n", wait ? "true" : "false", tp->num_workers);

	/* In this initial implementation, we don't bother to keep track of
	 * the worker thread IDs, so we can't force them to exit immediately
	 * by using pthread_cancel() - this is a TODO item.
	 *
	 * Instead, we set worker_exit to true to tell all of the worker
	 * threads to exit on their next loop, and then we wait for all of
	 * them to exit themselves. When each thread exits, it MUST decrement
	 * num_workers, and it must signal the exit_cond to wake up the thread
	 * waiting here. ADDITIONALLY, the thread here must signal (broadcast,
	 * really) the task_available condition on each loop, so that no worker
	 * threads keep waiting for tasks to arrive. Make sure that the broadcast
	 * happens BEFORE the wait!
	 */
	if (!wait) {
		tp_error("not supported yet: forced cancellation of worker threads. "
				"Will wait for them all to finish instead\n");
	}
	tp->worker_exit = true;
	kp_mutex_lock("threadpool_destroy", tp->lock);
	while (tp->num_workers > 0) {
		ret = pthread_cond_broadcast(tp->task_available);
		if (ret != 0) {
			tp_error("pthread_cond_broadcast() returned error=%d; skipping "
					"thread cleanup!\n", ret);
			break;
		}
		ret = pthread_cond_wait(tp->exit_cond, tp->lock);
		if (ret != 0) {
			tp_error("pthread_cond_wait() returned error=%d; skipping "
					"thread cleanup!\n", ret);
			break;
		}
	}
	kp_mutex_unlock("threadpool_destroy", tp->lock);

	/* Now free everything that we allocated: */
	kp_cond_destroy("exit cond", tp->exit);
	kp_cond_destroy("task_available cond", tp->task_available);
	kp_mutex_destroy("thread pool mutex", tp->lock);
	queue_destroy(tp->task_queue);
	kp_free((void **)(&tp), tp->use_nvm);

	tp_debug("successfully destroyed thread pool\n");
	return 0;
}
Пример #10
0
static void free_proto(ktap_state *ks, ktap_proto *f)
{
	kp_free(ks, f->code);
	kp_free(ks, f->p);
	kp_free(ks, f->k);
	kp_free(ks, f->lineinfo);
	kp_free(ks, f->locvars);
	kp_free(ks, f->upvalues);
	kp_free(ks, f);
}
Пример #11
0
static void free_ci(ktap_state *ks)
{
	ktap_callinfo *ci = ks->ci;
	ktap_callinfo *next;

	if (!ci)
		return;

	next = ci->next;
	ci->next = NULL;
	while ((ci = next) != NULL) {
		next = ci->next;
		kp_free(ks, ci);
	}
}
Пример #12
0
int queue_dequeue(queue *q, void **e) {
	element *head;

	if (!q || !e) {
		tp_error("got a NULL argument: q=%p, e=%p\n", q, e);
		return -1;
	}

	if (q->len == 0) {
		tp_debug("queue has no elements, returning 1\n");
		return 1;
	}
#ifdef TP_ASSERT
	if (!(q->head) || !(q->tail)) {
		tp_die("unexpected NULL pointer: q->head=%p, q->tail=%p\n",
				q->head, q->tail);
	}
#endif

	/* Remember, the "head" of the queue is the "front" of the queue - the
	 * element that we're dequeueing. Set the element pointer that will be
	 * returned, then set the new head to be the current head's next element.
	 * If we're dequeueing the last/only element in the queue, then both head
	 * and tail are set to NULL.
	 */
	head = q->head;
	*e = head->data;
	if (head->next == NULL) {
#ifdef TP_ASSERT
		if (q->len != 1) {
			tp_die("unexpected: queue length is %u, should be 1\n", q->len);
		}
		if (head != q->tail) {
			tp_die("unexpected: queue head %p and tail %p should be the "
					"same\n", head, q->tail);
		}
#endif
		q->tail = NULL;
	}
	q->head = head->next;
	q->len -= 1;

	/* Don't forget to free the element that we allocated: */
	kp_free((void **)(&head), q->use_nvm);

	tp_debug("returning element %p, queue length is now %u\n", *e, q->len);
	return 0;
}
Пример #13
0
void kp_obj_free_gclist(ktap_state_t *ks, ktap_obj_t *o)
{
	while (o) {
		ktap_obj_t *next;

		next = gch(o)->nextgc;
		switch (gch(o)->gct) {
		case ~KTAP_TTAB:
			kp_tab_free(ks, (ktap_tab_t *)o);
			break;
		case ~KTAP_TUPVAL:
			kp_freeupval(ks, (ktap_upval_t *)o);
			break;
		default:
			kp_free(ks, o);
		}
		o = next;
	}
}
Пример #14
0
void threadpool_destroy(threadpool *tp, bool wait) {
	unsigned int uret;

	if (!tp) {
		tp_error("got a NULL argument: tp=%p\n", tp);
		return;
	}
	tp_debug("destroying thread pool; wait=%s, thread pool currently has "
			"%u workers\n", wait ? "true" : "false", tp->num_workers);

	/* In this initial implementation, we don't bother to keep track of
	 * the worker thread IDs, so we can't force them to exit immediately
	 * by using pthread_cancel() - this is a TODO item.
	 *
	 * We destroy the thread pool by simply looping on the worker remove
	 * function until all of the threads have exited.
	 */
	if (!wait) {
		tp_error("not supported yet: forced cancellation of worker threads. "
				"Will wait for them all to finish instead\n");
	}
	while (tp->num_workers > 0) {
		uret = threadpool_remove_worker(tp, wait);
		if (uret == UINT32_MAX || uret != tp->num_workers) {
			tp_error("threadpool_remove_worker() returned unexpected "
					"value %u; all threads may not be cleaned up!\n", uret);
			break;
		}
	}
	tp_debug("done waiting, destroying threadpool with task counts "
			"pending=%u, active=%u, completed=%u\n", tp->tasks_pending,
			tp->tasks_active, tp->tasks_completed);

	/* Now free everything that we allocated: */
	kp_cond_destroy("exit cond", &(tp->exit_cond));
	kp_cond_destroy("task_available cond", &(tp->task_available));
	kp_mutex_destroy("thread pool mutex", &(tp->lock));
	queue_destroy(tp->task_queue);
	kp_free((void **)(&tp), tp->use_nvm);

	tp_debug("successfully destroyed thread pool\n");
	return;
}
Пример #15
0
void kp_free_all_gcobject(ktap_State *ks)
{
	Gcobject *o = G(ks)->allgc;
	Gcobject *next;

	while (o) {
		next = gch(o)->next;
		switch (gch(o)->tt) {
		case KTAP_TTABLE:
			kp_table_free(ks, (Table *)o);
			break;
		case KTAP_TPROTO:
			free_proto(ks, (Proto *)o);
			break;
		default:
			kp_free(ks, o);
		}
		o = next;
	}

	G(ks)->allgc = NULL;
}
Пример #16
0
void kp_table_resize(ktap_State *ks, Table *t, int nasize, int nhsize)
{
	int i;
	int oldasize = t->sizearray;
	int oldhsize = t->lsizenode;
	Node *nold = t->node;  /* save old hash ... */

	if (nasize > oldasize)  /* array part must grow? */
		setarrayvector(ks, t, nasize);

	/* create new hash part with appropriate size */
	setnodevector(ks, t, nhsize);

	if (nasize < oldasize) {  /* array part must shrink? */
		t->sizearray = nasize;
		/* re-insert elements from vanishing slice */
		for (i=nasize; i<oldasize; i++) {
			if (!ttisnil(&t->array[i]))
				kp_table_setint(ks, t, i + 1, &t->array[i]);
		}

		/* shrink array */
		kp_realloc(ks, t->array, oldasize, nasize, Tvalue);
	}

	/* re-insert elements from hash part */
	for (i = twoto(oldhsize) - 1; i >= 0; i--) {
		Node *old = nold+i;
		if (!ttisnil(gval(old))) {
			/* doesn't need barrier/invalidate cache, as entry was
			 * already present in the table
			 */
			setobj(ks, kp_table_set(ks, t, gkey(old)), gval(old));
		}
	}

	if (!isdummy(nold))
		kp_free(ks, nold); /* free old array */
}
Пример #17
0
void vector_free_contents(vector *v)
{
	unsigned long long i, count;

	if (v == NULL) {
		v_error("v is NULL\n");
		return;
	}

	count = v->count;
	for (i = 0; i < count; i++) {
		if (v->data[i]) {
			v_debug("freeing element %s from slot %llu\n",
					(char *)(v->data[i]), i);
			kp_free(&(v->data[i]), v->use_nvm);  //sets v->data[i] to NULL
		} else {
			/* could be a deleted value? */
			v_debug("NULL pointer in array, not freeing it\n");
		}
	}
	v_debug("successfully freed %llu elements from vector\n", count);
}
Пример #18
0
/*
 * allocate raw object with size.
 * The raw object allocated will be free when ktap thread exit,
 * so user don't have to free it.
 */
void *kp_rawobj_alloc(ktap_state *ks, int size)
{
	ktap_rawobj *obj;
	void *addr;
	
	addr = kp_zalloc(ks, size);
	if (unlikely(!addr)) {
		kp_error(ks, "alloc raw object size %d failed\n", size);
		return NULL;
	}

	obj = &kp_obj_newobject(ks, KTAP_TYPE_RAW, sizeof(ktap_rawobj), NULL)->rawobj;
	if (unlikely(!obj)) {
		kp_free(ks, addr);
		kp_error(ks, "alloc raw object failed\n");
		return NULL;
	}

	obj->v = addr;

	/* return address of allocated memory, not raw object */
	return addr;
}
Пример #19
0
size_t
track_flag_kp(const double kp_min, const double kp_max, satdata_mag *data, track_workspace *w)
{
  size_t i;
  size_t nflagged = 0;        /* number of points flagged */
  size_t ntrack_flagged = 0;  /* number of entire tracks flagged for UT */
  kp_workspace *kp_p;
  int s;

  if (data->n == 0)
    return 0;

  kp_p = kp_alloc(KP_IDX_FILE);

  for (i = 0; i < w->n; ++i)
    {
      track_data *tptr = &(w->tracks[i]);
      time_t t = satdata_epoch2timet(tptr->t_eq);
      double kp;

      s = kp_get(t, &kp, kp_p);
      if (s == 0 &&
          (kp < kp_min || kp > kp_max))
        {
          nflagged += track_flag_track(i, TRACK_FLG_KP, data, w);
          ++ntrack_flagged;
        }
    }

  fprintf(stderr, "track_flag_kp: flagged %zu/%zu (%.1f%%) tracks due to kp\n",
          ntrack_flagged, w->n, (double) ntrack_flagged / (double) w->n * 100.0);

  kp_free(kp_p);

  return nflagged;
} /* track_flag_kp() */
Пример #20
0
void kp_free_gclist(ktap_state *ks, ktap_gcobject *o)
{
	while (o) {
		ktap_gcobject *next;

		next = gch(o)->next;
		switch (gch(o)->tt) {
		case KTAP_TTABLE:
			kp_table_free(ks, (ktap_table *)o);
			break;
		case KTAP_TPROTO:
			free_proto(ks, (ktap_proto *)o);
			break;
#ifdef __KERNEL__
		case KTAP_TPTABLE:
			kp_ptable_free(ks, (ktap_ptable *)o);
			break;
#endif
		default:
			kp_free(ks, o);
		}
		o = next;
	}
}
Пример #21
0
static void cfunction_cache_exit(ktap_state *ks)
{
	kp_free(ks, G(ks)->cfunction_tbl);
}
Пример #22
0
/* histogram: key should be number or string, value must be number */
void kp_table_histogram(ktap_State *ks, Table *t)
{
	struct table_hist_record *thr;
	char dist_str[40];
	int i, ratio, total = 0, count = 0;

	thr = kp_malloc(ks, sizeof(*thr) * (t->sizearray + sizenode(t)));

	for (i = 0; i < t->sizearray; i++) {
		Tvalue *v = &t->array[i];

		if (isnil(v))
			continue;

		if (!ttisnumber(v))
			goto error;

		setnvalue(&thr[count++].key, i + 1);
		total += nvalue(v);
	}

	for (i = 0; i < sizenode(t); i++) {
		Node *n = &t->node[i];
		int num;

		if (isnil(gkey(n)))
			continue;

		if (!ttisnumber(gval(n)))
			goto error;

		num = nvalue(gval(n));
		setobj(ks, &thr[count].key, gkey(n));
		setobj(ks, &thr[count].val, gval(n));
		count++;
		total += nvalue(gval(n));
	}

	sort(thr, count, sizeof(struct table_hist_record), hist_record_cmp, NULL);

	kp_printf(ks, "%32s%s%s\n", "value ", DISTRIBUTION_STR, " count");
	dist_str[sizeof(dist_str) - 1] = '\0';
	for (i = 0; i < count; i++) {
		Tvalue *key = &thr[i].key;
		Tvalue *val = &thr[i].val;

		memset(dist_str, ' ', sizeof(dist_str) - 1);
		ratio = (nvalue(val) * (sizeof(dist_str) - 1)) / total;
		memset(dist_str, '@', ratio);

		if (ttisstring(key)) {
			char buf[32 + 1] = {0};
			char *keystr;

			if (strlen(svalue(key)) > 32) {
				strncpy(buf, svalue(key), 32-4);
				memset(buf + 32-4, '.', 3);
				keystr = buf;
			} else
				keystr = svalue(key);

			kp_printf(ks, "%32s |%s%-10d\n", keystr, dist_str,
					nvalue(val));
		} else
			kp_printf(ks, "%32d | %s%-10d\n", nvalue(key),
					dist_str, nvalue(val));
	}

	goto out;

 error:
	kp_printf(ks, "error: table histogram only handle "
			" (key: string/number val: number)\n");
 out:
	kp_free(ks, thr);
}
Пример #23
0
int threadpool_create(threadpool **tp, unsigned int num_workers,
		bool use_nvm) {
	int ret;
	unsigned int i, uret;

	if (!tp) {
		tp_error("got a NULL argument: tp=%p\n", tp);
		return -1;
	}
	if (num_workers == UINT32_MAX) {
		tp_error("invalid number of worker threads: %u\n", num_workers);
		return -1;
	}
	if (num_workers == 0) {
		tp_warn("creating a thread pool with 0 workers!\n");
	}
	tp_debug("creating new thread pool with %u workers\n", num_workers);

	kp_kpalloc((void **)tp, sizeof(threadpool), use_nvm);
	if (!(*tp)) {
		tp_error("malloc(threadpool) failed\n");
		return -1;
	}

	ret = queue_create(&((*tp)->task_queue), use_nvm);
	if (ret != 0) {
		tp_error("queue_create() returned error=%d\n", ret);
		goto free_pool;
	}
	ret = kp_mutex_create("thread pool mutex", &((*tp)->lock));
	if (ret != 0) {
		tp_error("kp_mutex_create() returned error=%d\n", ret);
		goto free_queue;
	}
	ret = kp_cond_create("task_available cond", &((*tp)->task_available));
	if (ret != 0) {
		tp_error("kp_cond_create(task_available) returned error=%d\n", ret);
		goto free_mutex;
	}
	ret = kp_cond_create("exit cond", &((*tp)->exit_cond));
	if (ret != 0) {
		tp_error("kp_cond_create(exit_cond) returned error=%d\n", ret);
		goto free_cond1;
	}
	(*tp)->worker_exit = false;
	(*tp)->use_nvm = use_nvm;

	/* Now that allocation is done, add the workers. threadpool_add_worker()
	 * will increment the num_workers count for us:
	 */
	(*tp)->num_workers = 0;
	for (i = 0; i < num_workers; i++) {
		uret = threadpool_add_worker(*tp);
		if (uret != i+1) {
			tp_error("threadpool_add_worker(%u) returned unexpected value "
					"%u\n", i, uret);
			for (; ; i--) {
				/* Don't wait, ignore return value: */
				threadpool_remove_worker(*tp, false);
				if (i == 0) {
					break;
				}
			}
			goto free_cond2;
		}
	}
	(*tp)->tasks_pending = 0;
	(*tp)->tasks_active = 0;
	(*tp)->tasks_completed = 0;

	tp_debug("successfully created new thread pool with %u threads\n",
			(*tp)->num_workers);
	return 0;

free_cond2:
	kp_cond_destroy("exit cond", &((*tp)->exit_cond));
free_cond1:
	kp_cond_destroy("task_available cond", &((*tp)->task_available));
free_mutex:
	kp_mutex_destroy("thread pool mutex", &((*tp)->lock));
free_queue:
	queue_destroy((*tp)->task_queue);
free_pool:
	kp_free((void **)tp, use_nvm);
	return -1;
}