⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libctx.c

📁 T-kernel 的extension源代码
💻 C
字号:
/* *---------------------------------------------------------------------- *    T-Kernel / Standard Extension * *    Copyright (C) 2006 by Ken Sakamura. All rights reserved. *    T-Kernel / Standard Extension is distributed  *      under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * *    Version:   1.00.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* *	libctx.c (libtkse) * *	Library context * *	Create and manage the independent context for the library at each task. *	Library context is managed by key. Execute the setting or referrence of the value *      to library context with the key. *	They are managed in matrix. * *		task1	task2	task3	... *	key1	value	value	value	... *	key2	value	value	value	... *	key3	value	value	value	... *	 :	 :	 :	 : * *	As above, different values are held at each task even with the same key. */#include <tk/tkernel.h>#include <sys/libs.h>#include <extension/proctask.h>#include <extension/errno.h>#include <stdlib.h>#include <sys/debug.h>#define	N_KEYENT	16	/* The increase unit of entry count for key table */#define	N_LIBCTX	16	/* The increase unit of library context */#define	KEYIDX(keyid)	( (UINT)((keyid) - 1) % N_KEYENT )#define	CTXIDX(tskid)	( (UINT)(tskid) % N_LIBCTX )/* * Library context */typedef struct LibCtx {	ID		tskid;			/* Task ID (0 free) */	void		*value;			/* The value of key */} LibCtx;/* * The control table of library context */typedef struct LibCtxTbl LibCtxTbl;struct LibCtxTbl {	LibCtxTbl	*next;			/* The link to next table ("NULL" termination) */	LibCtx		ctx[N_LIBCTX];		/* Library context */};/* * Key entry */typedef struct LibKey {	ID		keyid;			/* Key ID (0 free) */	void		(*destroy)( void* );	/* Destructor function* */	LibCtxTbl	*tbl;			/* Library context */} LibKey;/* * Key control table  */typedef struct LibKeyTbl LibKeyTbl;struct LibKeyTbl {	LibKeyTbl	*next;			/* The link to next table ("NULL" termination) */	LibKey		ent[N_KEYENT];		/* Key entry */};/* * The lock for exclusive access control */#define	LockLibCtx()	(void)_lib_lock(_LL_LIBCTX, TRUE)#define	UnlockLibCtx()	_lib_unlock(_LL_LIBCTX)#define TSD_DAL_VAL_M1	(-1)#define TSD_DLK_KID_M1	(-1)LOCAL ID myTaskID( void );LOCAL BOOL isTaskExist( ID tskid );LOCAL LibKey* search_LibKey( ID keyid );LOCAL LibCtx* search_LibCtx( LibKey *ke, ID tskid );LOCAL LibCtx* new_LibCtx( LibKey *ke, ID tskid );/* ------------------------------------------------------------------------ *//* * Invoking task ID */LOCAL ID myTaskID( void ){	return tkse_get_tid();}/* * Check if the task is existent */LOCAL BOOL isTaskExist( ID tskid ){	/* Only the task in invoking process is valid */	return ( tkse_chg_pri(tskid, 0, P_REL|P_TASK) >= 0 )? TRUE: FALSE;}/* ------------------------------------------------------------------------ */LOCAL	LibKeyTbl	*LibKeyTblTop = NULL;	/* Key control table */LOCAL	ID		LastKeyID = 0;		/* Last allocated key ID *//* * Search the key */LOCAL LibKey* search_LibKey( ID keyid ){	LibKeyTbl	*kt;	W		idx = (W)KEYIDX(keyid);	for ( kt = LibKeyTblTop; kt != NULL; kt = kt->next ) {		if ( kt->ent[idx].keyid == keyid ) {			return &kt->ent[idx];		}	}	return NULL;}/* * Search the value (search library context) */LOCAL LibCtx* search_LibCtx( LibKey *ke, ID tskid ){	LibCtxTbl	*ct;	W		idx = (W)CTXIDX(tskid);	for ( ct = ke->tbl; ct != NULL; ct = ct->next ) {		if ( ct->ctx[idx].tskid == tskid ) {			return &ct->ctx[idx];		}	}	return NULL;}/* * Add the value (allocate library context) */LOCAL LibCtx* new_LibCtx( LibKey *ke, ID tskid ){	LibCtxTbl	*ct;	W		idx = (W)CTXIDX(tskid);	/* Search whether value is already set or not */	for ( ct = ke->tbl; ct != NULL; ct = ct->next ) {		if ( ct->ctx[idx].tskid == 0 ) {			break;		}		/* Also handle the already terminated task as free */		if ( !isTaskExist(ct->ctx[idx].tskid) ) {			break;		}	}	if ( ct == NULL ) {		/* Create new table */		ct = calloc(1, sizeof(LibCtxTbl));		if ( ct == NULL ) {			goto err_ret;		}		ct->next = ke->tbl;		ke->tbl = ct;	}	return &ct->ctx[idx];err_ret:	DEBUG_PRINT(("new_LibCtx err = %d\n", E_NOMEM));	return NULL;}/* * Create the key *	Return value	>0 ID Key ID *			<0 error */EXPORT ER _CreateLibCtxKey( void (*destroy)( void* ) ){	LibKeyTbl	*kt;	ID		keyid;	W		i = 0;	ER		err;	LockLibCtx();	/* Reject the key creation during the end processings */	if ( LastKeyID < 0 ) {		err = E_CTX;		goto err_ret;	}	/* Search the free entry */	keyid = LastKeyID;	for ( kt = LibKeyTblTop; kt != NULL; kt = kt->next ) {		for ( i = 0; i < N_KEYENT; i++ ) {			if ( kt->ent[i].keyid == 0 ) {				break;			}		}		if ( i < N_KEYENT ) {			break;		}		keyid -= N_KEYENT;	}	if ( kt == NULL ) {		/* Create the new table */		kt = calloc(1, sizeof(LibKeyTbl));		if ( kt == NULL ) {			err = E_NOMEM;			goto err_ret;		}		kt->next = LibKeyTblTop;		LibKeyTblTop = kt;		i = 0;		if ( LastKeyID == 0 ) {			/* Register the end processing only at first time */			(void)atexit(_DeleteAllLibCtx);			(void)__atdelctx(_DeleteLibCtxTask);		}		keyid = LastKeyID += N_KEYENT;	}	keyid -= (N_KEYENT - 1) - i;	/* Register the key */	kt->ent[i].keyid   = keyid;	kt->ent[i].destroy = destroy;	kt->ent[i].tbl     = NULL;	UnlockLibCtx();	return keyid;err_ret:	UnlockLibCtx();	DEBUG_PRINT(("_CreateLibCtxKey err = %d\n", err));	return err;}/* * Set the value */EXPORT ER _SetLibCtx( ID keyid, void *value ){	ID	tskid = myTaskID();		/* Invoking task ID* */	LibKey	*ke;	LibCtx	*ce;	void	(*destroy)( void* ) = NULL;	void	*destroy_value = NULL;	ER	err;	LockLibCtx();	/* Reject the value setting during the end processings */	if ( LastKeyID < 0 ) {		err = E_CTX;		goto err_ret;	}	/* Search the key entry */	ke = search_LibKey(keyid);	if ( ke == NULL ) {		err = E_NOEXS;		goto err_ret;	}	/* Search whether value is already set or not */	ce = search_LibCtx(ke, tskid);	if ( ce == NULL ) {		/* Allocate the entry for new registartion */		ce = new_LibCtx(ke, tskid);		if ( ce == NULL ) {			err = E_LIMIT;			goto err_ret;		}		if ( ce->tskid != 0 ) {			/* Discard the value of already terminated task, and set it to free */			destroy = ke->destroy;			destroy_value = ce->value;		}	}	/* Set the value */	ce->tskid = tskid;	ce->value = value;	UnlockLibCtx();	if ( destroy != NULL ) {		/* Discard the value allocated to the already terminated task */		(*destroy)(destroy_value);	}	return E_OK;err_ret:	UnlockLibCtx();	DEBUG_PRINT(("_SetLibCtx err = %d\n", err));	return err;}/* * Refer to the value */EXPORT ER _GetLibCtx( ID keyid, void **value ){	ID	tskid = myTaskID();	LibKey	*ke;	LibCtx	*ce;	ER	err;	LockLibCtx();	/* Search the key */	ke = search_LibKey(keyid);	if ( ke == NULL ) {		err = E_NOEXS;		goto err_ret;	}	/* Search the value*/	ce = search_LibCtx(ke, tskid);	if ( ce == NULL ) {		err = E_NOEXS;		goto err_ret;	}	*value = ce->value;	UnlockLibCtx();	return E_OK;err_ret:	UnlockLibCtx();	DEBUG_PRINT(("_GetLibCtx err = %d\n", err));	return err;}/* * Delete the key */EXPORT ER _DeleteLibCtxKey( ID keyid ){	LibKey		*ke;	LibCtxTbl	*ct, *next;	W		i;	ER		err;	LockLibCtx();	/* Reject the key deletion during the end processings */	if ( LastKeyID < 0 ) {		err = E_CTX;		goto err_ret;	}	/* Search the key */	ke = search_LibKey(keyid);	if ( ke == NULL ) {		err = E_NOEXS;		goto err_ret;	}	ke->keyid = TSD_DLK_KID_M1; /* Indicate the deletion processing to be in progress */	UnlockLibCtx();	/* Discard the all values */	for ( ct = ke->tbl; ct != NULL; ct = next ) {		for ( i = 0; i < N_LIBCTX; i++ ) {			if ( ct->ctx[i].tskid == 0 ) {				continue;			}			(*ke->destroy)(ct->ctx[i].value);		}		next = ct->next;		free(ct);	}	LockLibCtx();	ke->keyid = 0;			/* Delete the key */	ke->tbl = NULL;	UnlockLibCtx();	return E_OK;err_ret:	UnlockLibCtx();	DEBUG_PRINT(("_DeleteLibCtxKey err = %d\n", err));	return err;}/* * Delete the library context of specification task(end of task) */EXPORT void _DeleteLibCtxTask( ID tskid ){	ID	keyid;	LibKey	*ke;	LibCtx	*ce;	void	(*destroy)( void* );	void	*destroy_value = NULL;	/* Search the library context at the corresponding task from all keys */	for ( keyid = 1; keyid <= LastKeyID; keyid++ ) {		LockLibCtx();		destroy = NULL;		ke = search_LibKey(keyid);		ce = search_LibCtx(ke, tskid);		if (( ke != NULL )		  && ( ce != NULL )) {			destroy = ke->destroy;			destroy_value = ce->value;			ce->tskid = 0;		}		UnlockLibCtx();		if ( destroy != NULL ) {			/* Discard the value */			(*destroy)(destroy_value);		}	}}/* * Delete the all library contexts (processing at the time of end) */EXPORT void _DeleteAllLibCtx( void ){	LibKeyTbl	*kt;	LibCtxTbl	*ct;	void		*next;	W		i, j;	LockLibCtx();	LastKeyID = TSD_DAL_VAL_M1;			/* Indicate the end processing to be in progress */	UnlockLibCtx();	/* Discard all the values */	for ( kt = LibKeyTblTop; kt != NULL; kt = kt->next ) {		for ( i = 0; i < N_KEYENT; i++ ) {			if ( kt->ent[i].keyid == 0 ) {				continue;			}			for ( ct = kt->ent[i].tbl; ct != NULL; ct = ct->next ) {				for ( j = 0; j < N_LIBCTX; j++ ) {					if ( ct->ctx[j].tskid == 0 ) {						continue;					}					ct->ctx[j].tskid = 0;					(*kt->ent[i].destroy)(ct->ctx[j].value);				}			}		}	}	/* Delete the control table */	LockLibCtx();	for ( kt = LibKeyTblTop; kt != NULL; kt = next ) {		for ( i = 0; i < N_KEYENT; i++ ) {			for ( ct = kt->ent[i].tbl; ct != NULL; ct = next ) {				next = ct->next;				free(ct);			}		}		next = kt->next;		free(kt);	}	LibKeyTblTop = NULL;	UnlockLibCtx();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -