示例#1
0
EXPORT struct sttask *
stpool_task_new(stpool_t *pool, const char *name,
				void (*run)(struct sttask *ptask),
				void (*err_handler)(struct sttask *ptask, long reasons),
				void *arg) 
{
	int e;
	ctask_t *ptask; 
	
	/**
	 * Does the pool support the Waitable tasks ?
	 */
	if (pool && !(eFUNC_F_TASK_EX & pool->efuncs)) {
		MSG_log(M_POOL, LOG_ERR,
				"Only ROUTINE tasks are supported by this pool(%s/%p) efuncs(%p).\n",
				pool->desc, pool, pool->efuncs);
		return NULL;
	}

	if (!(ptask = __stpool_cache_get(NULL)))
		return NULL;
	
	__stpool_task_INIT(ptask, name, run, err_handler, arg);
	if (pool && (e = __stpool_task_set_p(ptask, pool))) {
		MSG_log2(M_POOL, LOG_ERR,
			"__task_set_p: code(%d).",
			e);
		return NULL;
	}

	return TASK_CAST_UP(ptask);
}
示例#2
0
int  
objpool_ctor2(objpool_t *p, const char *name, size_t objlen, size_t nreserved, int nlimit_cache, OSPX_pthread_mutex_t *cache_lock)
{
	/**
	 * A block must can store at least 20 objects 
	 */
	int n = 20, page_size = 4096, dummy = 50;
	
	if (objlen >= 256) {
		n = 8;
		page_size = 8096;
	}
	
	p->objlen = objlen;
	p->blocks = NULL;
	p->iblocks = p->ialloc = 0;
	p->block_size = (n + sizeof(obj_block_t) + dummy +
		page_size - 1) / page_size * page_size;
	p->block_nobjs = (p->block_size - sizeof(obj_block_t)) / objlen;
	p->ntotal = p->nput = 0;
	
	MSG_log(M_FOBJP, LOG_INFO,
			"Initializing fast objpool(\"%s\"/%p) ...\n", 
			name, p);

	/**
	 * Initialize the cache object 
	 */
	if (smcache_init2(&p->smc, name, !nlimit_cache ? p->block_nobjs : nlimit_cache, 
			cache_lock, CACHE_F_LOCK_CREATER, p, objpool_get, 
			objpool_put, FUNC_ALWAYS_NEED_DESTROY)) {
		MSG_log2(M_FOBJP, LOG_ERR,
			"cache_init error");
		return -1;
	}
	
	/**
	 * Reserve some objects for the app if it has been 
	 * requested by user 
	 */
	if (nreserved > 0)
		smcache_reserve(&p->smc, nreserved);

	return 0;
}
示例#3
0
static void *
objpool_get(void *opaque) 
{
	size_t i = 0, n = 0, n_inc = 0;
	objpool_t *p = opaque;
	smlink_q_t *putq;
	void *m0 = NULL, *m1;
	
	/**
	 * Scan the free queue of the blocks 
	 */
	if (p->nput) {
		assert (p->ntotal >= p->nput);
		for (i=0; i<p->iblocks && p->nput && n_inc < 5; i++) {
			putq = &p->blocks[i].putq;
			
			/**
			 * If there are free objects existing in the 
			 * blocks, we add some few of them into the 
			 * cache again 
			 */
			if (!smlink_q_empty(putq)) {
				n = smlink_q_size(putq);
				p->nput -= n;
	
				assert (n < p->block_nobjs);
				if (!m0) {
					m0 = smlink_q_pop(putq);
					n -= 1;
				}

				if (n) {
					n_inc += n; 
					smcache_add_ql(&p->smc, putq);
					INIT_SMLINK_Q(putq);
				}	
			}
		}
		assert (m0);
		return m0;
	}

	/**
	 * If we can not get any task objects from the 
	 * free queue, we try to create a new block to 
	 * get more task objects 
	 */
	if (!(m0 = calloc(1, p->block_size))) {
		MSG_log2(M_FOBJP, LOG_ERR,
				"obj_create2: no memory.");
		return NULL;
	}
		
	/** 
	 * Allocate a memory to store the block 
	 */
	if (p->ialloc == p->iblocks) {
		n_inc = 3;

		if (p->iblocks)
			m1 = realloc(p->blocks, sizeof(obj_block_t) *(p->iblocks + n_inc));
		else
			m1 = malloc(sizeof(obj_block_t) * n_inc);

		if (!m1) {
			MSG_log2(M_FOBJP, LOG_ERR,
				"obj_create2: no memory.");
			free(m0);
			return NULL;
		}
		p->ialloc += n_inc;
		p->blocks = m1;
	}
		
	/**
	 * Sort the block according to its objects address 
	 */
	if (p->iblocks) {
		size_t l = 0, r = p->iblocks -1;
		
		for (;r>l;) {	
			if ((char *)m0 < p->blocks[(l+r)/2].begin) 
				r = (l+r)/2 - 1;	
			else 
				l = (l+r)/2 + 1;	
		}
		/**
		 * Be carefull: overflow 
		 */
		assert (l >= 0 && (r < 0 || r <= (p->iblocks - 1)));
		
		if ((char *)m0 > p->blocks[l].begin) 
			l += 1;	
	
		if (l <= p->iblocks - 1)
			memmove(p->blocks + l + 1, p->blocks + l, 
				(p->iblocks - l) * sizeof(obj_block_t));	
		i = l;
	}
	
	/**
	 * Initialize the block 
	 */
	{
		obj_block_t *ob = &p->blocks[i];
		
		ob->begin = m0;
		ob->end = (char *)m0 + p->block_nobjs * p->objlen;
		putq = &ob->putq;
		INIT_SMLINK_Q(putq);
				
		assert (i==0 || p->blocks[i].begin >= p->blocks[i-1].begin);
		/**
		 * Add the objects into the cache 
		 */
		if (p->block_nobjs > 1) {
			for (i=1; i<p->block_nobjs; i++) 
				smlink_q_push(putq, 
							 ob->begin + i * p->objlen
							 );	
			smcache_add_ql(&p->smc, putq);
			INIT_SMLINK_Q(putq);		
		}
	}
	assert (p->blocks[p->iblocks].begin != 0 &&
	        p->blocks[p->iblocks].end > p->blocks[p->iblocks].begin);
	++ p->iblocks;
	p->ntotal += p->block_nobjs;

	return m0;
}
示例#4
0
EXPORT stpool_t * 
stpool_create(const char *desc, long eCAPs, int maxthreads, int minthreads, int suspend, int pri_q_num) 
{
	cpool_t *pool = NULL;
	long elibCAPs;
	int  nfuncs;
	const char *fac_desc;
	const cpool_factory_t *fac;
	char eCAPs_buffer[400];
	
	struct fac_candidate {
		const char *fac_desc;
		int nfuncs;
		long eCAPs;
		const cpool_factory_t *fac;
	} fac_sel[20];
	int idx, sel_idx = 0;

	
	/**
	 * It does not need to load the ospx library since 
     * we do not call any APIs who must use the TLS datas.
	 */
	MSG_log(M_POOL, LOG_INFO,
			"Request creating a pool(\"%s\") efuncs(%s) ...\n",
			desc, __eCAPs_desc(eCAPs, eCAPs_buffer));

	/**
	 * Select the best templates to create the pool 
	 */
	for (fac=first_factory(&fac_desc); fac; fac=next_factory(&fac_desc)) {
		elibCAPs = __enum_CAPs(fac, &nfuncs);
		if ((elibCAPs & eCAPs) == eCAPs) {
			MSG_log(M_POOL, LOG_DEBUG,
					"Find a Factory(\"%s\" scores(%d), nfuns(%d)): %s\n\n",
					fac_desc, fac->scores, nfuncs, __eCAPs_desc(elibCAPs, eCAPs_buffer));
			
			/**
			 * We skip it if the entry is full
			 */
			if (sel_idx == sizeof(fac_sel)/sizeof(*fac_sel))
				continue;
			
			/**
			 * Add the factory into our candidate entries
			 */
			for (idx=0; idx<sel_idx; idx++) {
				if (fac->scores > fac_sel[idx].fac->scores ||
					(fac->scores == fac_sel[idx].fac->scores && nfuncs > fac_sel[idx].nfuncs)) {
					memmove(fac_sel + idx + 1, fac_sel + idx, (sel_idx - idx) * sizeof(struct fac_candidate));
					break;
				}
			}
			fac_sel[idx].fac_desc = fac_desc;
			fac_sel[idx].nfuncs = nfuncs;
			fac_sel[idx].eCAPs = elibCAPs;
			fac_sel[idx].fac = fac;
			++ sel_idx;
		}
	}
	
	if (!sel_idx) {
		MSG_log(M_POOL, LOG_ERR,
				"Can not find any pool template to satify user. eCAPs(%p) (%s)\n",
				eCAPs, stpool_version());
		return NULL;
	}
	
	for (idx=0; idx<sel_idx; idx++) {
		MSG_log(M_POOL, LOG_INFO,
				"Factory(\"%s\" scores(%d) nfuns(%d)) try to service us. lib_eCAPs(%p) user_eCAPs(%p)\n",
				fac_sel[idx].fac_desc, fac_sel[idx].fac->scores, fac_sel[idx].nfuncs, fac_sel[idx].eCAPs, eCAPs);

		if ((pool = fac_sel[idx].fac->create(desc, maxthreads, minthreads, pri_q_num, suspend))) 
			break;

		MSG_log2(M_POOL, LOG_ERR,
			"Failed to create the pool: Factory(\"%s\"/%p).",
			fac_sel[idx].fac_desc, fac_sel[idx].fac);
	}

	if (idx != sel_idx && ME_HAS(pool, atexit))
		ME_CALL(pool, atexit)(pool->ins, __stpool_atexit, pool);

	return pool;
}