📄 gthreads.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. * *---------------------------------------------------------------------- *//* * gthreads.c (libtkse) * * Multi-thread support routine for "gcc"'s exclusive use */#include <basic.h>#include <tk/tkernel.h>#include <sys/libs.h>#include <extension/errno.h>#include "gthreads.h"LOCAL int thread_mutex_init( long *mutex );LOCAL int thread_mutex_lock( long *mutex );LOCAL int thread_mutex_unlock( long *mutex );LOCAL void thread_mutex_setup( void );LOCAL int thread_key_create( long *keyp, void (*destructor)(void*) );LOCAL int thread_key_set( long key, void *value );LOCAL int thread_key_get( long key, void **valuep );LOCAL void thread_key_setup( void );LOCAL int thread_once( long *once_block, void (*init_routine)() );LOCAL int _1st_thread_once( long *once_block, void (*init_routine)() );#define TSD_TKC_RTN_M1 (-1)/* * Lock uses the common and single library shared lock in the processing of "mutex" , * once_block, and user information. * * It is based on the following assumption. * - Use "_thread_once" in calling(invoking) "_thread_mutex_init" and * "_thread_key_create". * libgcc2.c:eh_context_initialize(), * frame.c:init_object_mutex_once() * - Exclude "_thread_key_create()" at caller. * - "_thread_key_set()" and "_thread_key_get()" are not used together with "mutex" * and once_block. * - Initialize only one "mutex" * ("_thread_mutex_lock()" and "_thread_mutex_unlock()" are not used by nesting) * These are truths in implementing "gcc2.95.2" *//* ------------------------------------------------------------------------ *//* * Mutex * * Use a single lock since only one mutex is requested in implementing "gcc2.95.2". *//* * Initialize the mutex * Return value 0:normal <0:error */LOCAL int thread_mutex_init( long *mutex ){ return 0;}/* * Lock the mutex * Return value 0:normal <0:error */LOCAL int thread_mutex_lock( long *mutex ){ return _lib_lock(_LL_GCC, TRUE);}/* * Unlock the mutex * Return value 0:normal <0:error */LOCAL int thread_mutex_unlock( long *mutex ){ _lib_unlock(_LL_GCC); return 0;}/* * Setup-processing at first call. * Execute the setup at first call of "thread_once()"on the assumption that it is used * in combination with "thread_once()". *//* Multi-thread-compliant */LOCAL void thread_mutex_setup( void ){ if ( _isUseMT() != 0 ) { /* Multi-thread-compliant */ _thread_mutex_lock = thread_mutex_lock; _thread_mutex_unlock = thread_mutex_unlock; _thread_mutex_init = thread_mutex_init; } else { /* Non-multi-thread-compliant */ _thread_mutex_lock = NULL; _thread_mutex_unlock = NULL; _thread_mutex_init = NULL; }}EXPORT int (*_thread_mutex_init)();EXPORT int (*_thread_mutex_lock)();EXPORT int (*_thread_mutex_unlock)();/* ------------------------------------------------------------------------ *//* * Thread-specific information *//* * Create the key * Create the area to store the thread-specific information, and the key to refer to the area. * Call "destructor" when exiting thread, and discard the value set to the key. * Return value 0:normal <0:error */LOCAL int thread_key_create( long *keyp, void (*destructor)(void*) ){ ID keyid; keyid = _CreateLibCtxKey(destructor); if ( keyid < E_OK ) { return TSD_TKC_RTN_M1; } *keyp = keyid; return 0;}/* * Set the value to key * Set the value to the thread-specific information indicated by key. * Return value 0:normal <0:error */LOCAL int thread_key_set( long key, void *value ){ return _SetLibCtx(key, value);}/* * Refer to the value of key * Refer to the value from the thread-specific information indicated by key * Return value 0:normal <0:error */LOCAL int thread_key_get( long key, void **valuep ){ return _GetLibCtx(key, valuep);}/* * Setup-processing at first call * Execute a setup at the first call of "thread_once()"on the assumption that it is used * in combination with "thread_once()". */LOCAL void thread_key_setup( void ){ if ( _isUseMT() != 0 ) { /* Multi-thread-compliant */ _thread_key_create = thread_key_create; _thread_key_set = thread_key_set; _thread_key_get = thread_key_get; } else { /* Non-multi-thread-compliant */ _thread_key_create = NULL; _thread_key_set = NULL; _thread_key_get = NULL; }}EXPORT int (*_thread_key_create)();EXPORT int (*_thread_key_set)();EXPORT int (*_thread_key_get)();/* ------------------------------------------------------------------------ *//* * Once_block *//* * Once_block * Exclusively execute "init_routine" only once. * Use "once_block" as the already executed flag. * Return value 0:normal <0:error */LOCAL int thread_once( long *once_block, void (*init_routine)() ){ if ( *once_block == (long)0 ) { (void)_lib_lock(_LL_GCC, TRUE); if ( *once_block == (long)0 ) { (*init_routine)(); *once_block = 1; } _lib_unlock(_LL_GCC); } return 0;}/* * Setup-processing at first call */LOCAL int _1st_thread_once( long *once_block, void (*init_routine)() ){ (void)_lib_lock(_LL_GCC, TRUE); /* Set up "once_block" */ if ( _isUseMT() != 0 ) { /* Multi-task-compliant */ _thread_once = thread_once; } else { /* Non-multi-task-compliant */ _thread_once = NULL; } /* Set up mutex */ thread_mutex_setup(); /* Set up "thread_key" */ thread_key_setup(); _lib_unlock(_LL_GCC); return thread_once(once_block, init_routine);}EXPORT int (*_thread_once)() = _1st_thread_once;/* ------------------------------------------------------------------------ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -