📄 libctx.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 + -