Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* USMID @(#) clibinc/cray/mtlock.h 92.2 07/26/99 12:57:34 */ 00002 00003 00004 /* 00005 00006 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00007 00008 This program is free software; you can redistribute it and/or modify it 00009 under the terms of version 2 of the GNU General Public License as 00010 published by the Free Software Foundation. 00011 00012 This program is distributed in the hope that it would be useful, but 00013 WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00015 00016 Further, this software is distributed without any warranty that it is 00017 free of the rightful claim of any third person regarding infringement 00018 or the like. Any license provided herein, whether implied or 00019 otherwise, applies only to this software file. Patent licenses, if 00020 any, provided herein do not apply to combinations of this program with 00021 other software, or any other product whatsoever. 00022 00023 You should have received a copy of the GNU General Public License along 00024 with this program; if not, write the Free Software Foundation, Inc., 59 00025 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00026 00027 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00028 Mountain View, CA 94043, or: 00029 00030 http://www.sgi.com 00031 00032 For further information regarding this notice, see: 00033 00034 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00035 00036 */ 00037 00038 #ifndef _CRAY_MTLOCK_H 00039 #define _CRAY_MTLOCK_H 00040 00041 /* 00042 * Include section. 00043 */ 00044 00045 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 00046 #include <cray/libuni.h> 00047 #endif 00048 00049 #if defined(__mips) 00050 #include <mutex.h> 00051 #elif defined(_SOLARIS) 00052 #include <synch.h> 00053 #elif defined(_LITTLE_ENDIAN) && !defined(__sv2) 00054 /* do not include pthread.h yet */ 00055 #endif 00056 00057 00058 /* 00059 * Typedef section. 00060 */ 00061 00062 /* 00063 * The plock_t typedef should be used for pthread-locking. 00064 * The mpplock_t typedef should be used for PE-locking. 00065 */ 00066 #if defined(__mips) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) 00067 typedef unsigned long plock_t; 00068 #elif defined(_SOLARIS) 00069 typedef mutex_t plock_t; 00070 #elif defined(_LITTLE_ENDIAN) && !defined(__sv2) 00071 /* do not use typedef pthread_mutex_t plock_t yet */ 00072 typedef unsigned long plock_t; 00073 #else 00074 typedef volatile long plock_t; 00075 #endif 00076 typedef long mpplock_t; 00077 00078 /* 00079 * Macros section. 00080 */ 00081 00082 /* 00083 * DECL_LOCK(name) declares a pthread-lock word with name 'name'. 00084 * DECL_MPP_LOCK(name) declares a PE-lock word with name 'name'. 00085 * EXTERN_LOCK(name) is used in modules which reference a pthread-lock. 00086 * EXTERN_MPP_LOCK(name) is used in modules which reference a PE-lock. 00087 */ 00088 00089 #define DECL_LOCK(name) plock_t name; /* static initialized to 0 */ 00090 #define DECL_MPP_LOCK(name) mpplock_t name; /* static initialized to 0 */ 00091 #define EXTERN_LOCK(name) extern plock_t name; 00092 #define EXTERN_MPP_LOCK(name) extern mpplock_t name; 00093 00094 /* 00095 * MULTI_ON tests for the existence of multi-tasking in a program. 00096 */ 00097 00098 #if defined(_CRAY1) || defined(_LIB_UMK) 00099 #define MULTI_ON ($MULTION == 0) 00100 #elif defined(__mips) 00101 #define MULTI_ON 1 00102 #elif defined(_SOLARIS) 00103 #define MULTI_ON 1 00104 #else 00105 #define MULTI_ON 0 00106 #endif 00107 00108 /* 00109 * MEM_LOCK and MEM_UNLOCK are general library locking macros. They 00110 * take one argument: 00111 * 00112 * lock - the address of the word used as a software lock. 00113 * 00114 * These macros are no-ops if multitasking is not being used by the program. 00115 */ 00116 #if defined(_CRAY1) || defined(_LIB_UMK) 00117 #define MEM_LOCK(lock) { if (MULTI_ON) _inline_mtlock(lock); } 00118 #define MEM_UNLOCK(lock) { if (MULTI_ON) _inline_mtunlock(lock); } 00119 00120 #elif defined(__mips) || (defined(_LITTLE_ENDIAN) && defined(__sv2)) 00121 #define MEM_LOCK(lock) { while (__lock_test_and_set((lock),1L)); } 00122 #define MEM_UNLOCK(lock) { *(lock) = 0; } 00123 00124 #elif defined(_SOLARIS) 00125 #define MEM_LOCK(lock) mutex_lock(lock); 00126 #define MEM_UNLOCK(lock) mutex_unlock(lock); 00127 00128 #elif defined(_LITTLE_ENDIAN) && !defined(__sv2) 00129 /* do not use the following yet */ 00130 /* define MEM_LOCK(lock) pthread_mutex_lock(lock) */ 00131 /* define MEM_UNLOCK(lock) pthread_mutex_unlock(lock) */ 00132 #define MEM_LOCK(lock) 00133 #define MEM_UNLOCK(lock) 00134 00135 #else 00136 #define MEM_LOCK(lock) 00137 #define MEM_UNLOCK(lock) 00138 00139 #endif 00140 00141 /* 00142 * LMEM_LOCK and LMEM_UNLOCK are general library locking macros. They 00143 * take one argument: 00144 * 00145 * lock - the address of the word used as a software lock. 00146 * 00147 * These macros are identical to MEM_LOCK and MEM_UNLOCK, except that 00148 * they do not check MULTI_ON. 00149 */ 00150 #if defined(_CRAY1) || defined(_LIB_UMK) 00151 #define LMEM_LOCK(lock) { _inline_mtlock(lock); } 00152 #define LMEM_UNLOCK(lock) { _inline_mtunlock(lock); } 00153 00154 #else 00155 00156 #define LMEM_LOCK(lock) MEM_LOCK(lock) 00157 #define LMEM_UNLOCK(lock) MEM_UNLOCK(lock) 00158 00159 #endif 00160 00161 /* 00162 * MPP_LOCK and MPP_UNLOCK are general library locking macros for 00163 * the MPP. They take one argument: 00164 * 00165 * lock - the address of the word used as a software lock. 00166 * 00167 * NOTE: the DECL_MPP_LOCK macro should be used to declare a lock word. 00168 */ 00169 00170 #ifdef _CRAYMPP 00171 #define MPP_LOCK(lock) { if (_num_pes() > 1) _shmem_set_lock(lock); } 00172 #define MPP_UNLOCK(lock) { if (_num_pes() > 1) _shmem_clear_lock(lock); } 00173 #else 00174 #define MPP_LOCK(lock) 00175 #define MPP_UNLOCK(lock) 00176 #endif 00177 00178 /* 00179 * LIB_LOCK and LIB_UNLOCK are currently used by libc for the 00180 * multi-tasking version of the library. They take one argument: 00181 * 00182 * index - index into the table of library locks 00183 * 00184 * NOTE: This macro is only active if the MULTIP macro is set. 00185 */ 00186 00187 #ifdef MULTIP 00188 #define LIB_LOCK(index) MEM_LOCK(&__lib_locks[index]) 00189 #define LIB_UNLOCK(index) MEM_UNLOCK(&__lib_locks[index]) 00190 #else 00191 #define LIB_LOCK(index) 00192 #define LIB_UNLOCK(index) 00193 #endif 00194 00195 /* 00196 * This section has the indexes used by the LIB_LOCK macro. 00197 */ 00198 00199 #define ENVIRON_LOCK 0 /* Environment lock */ 00200 #define TRACEBACK_LOCK 1 /* Traceback lock */ 00201 #define MESSAGE_LOCK 2 /* Message system lock */ 00202 #define LIB_LOCK_MAX 64 /* Size of lock array */ 00203 00204 /* 00205 * Externals section. 00206 */ 00207 00208 #ifdef MULTIP 00209 extern plock_t __lib_locks[]; /* array of library locks */ 00210 #pragma common __lib_locks 00211 #endif 00212 00213 #if defined(_CRAY1) || defined(_LIB_UMK) 00214 00215 #pragma _CRI soft $MULTION 00216 extern $MULTION(void); /* must be a parcel reference */ 00217 00218 #pragma _CRI soft _lockon 00219 extern int _lockon(plock_t *); 00220 00221 #pragma _CRI soft _lockoff 00222 extern int _lockoff(plock_t *); 00223 00224 #endif 00225 00226 /* 00227 * Inline functions section. 00228 */ 00229 00230 #define SIGNBIT (1<<63) 00231 00232 /* 00233 * _inline_mtlock is functionally equivalent to _lockon (CX/CEA systems) 00234 * or _mtlock (CRAY-2 systems).. 00235 * 00236 * _inline_mtunlock is functionally equivalent to _lockoff (CX/CEA systems) 00237 * or _mtunlock (CRAY-2 systems). 00238 * 00239 * Because both are inline functions, they perform better than the other locking 00240 * functions when there is no lock contention. The existence of lock 00241 * contention is detected when: 00242 * 00243 * 1) _inline_mtlock detects a locked lock. 00244 * or 2) (CX/CEA systems) _inline_mtunlock detects a queue of tasks waiting 00245 * for this lock. 00246 * 00247 * When lock contention is detected the lower level lock management routines 00248 * are called. 00249 */ 00250 #if defined(_CRAY1) || defined(_LIB_UMK) 00251 00252 extern void _semts(int); 00253 extern void _semclr(int); 00254 extern void _cmr(void); 00255 00256 #define TSKLK 2 00257 00258 #pragma _CRI inline _inline_mtlock 00259 static void 00260 _inline_mtlock(plock_t *lck) 00261 { 00262 _semts(TSKLK); 00263 /* 00264 * Since lck's type has the "volatile" qualifier, the load of *lck will 00265 * bypass cache on CRAY TS. 00266 */ 00267 if (*lck != 0) { /* Word is locked; put _lockon to work */ 00268 _semclr(TSKLK); 00269 _lockon(lck); 00270 } 00271 else { /* Lock word is unlocked */ 00272 *lck = SIGNBIT; 00273 00274 #if defined(_CRAY1) && defined(_ADDR64) /* CRAY TS */ 00275 /* 00276 * Clear the data cache in preparation for the critical 00277 * region we are about to enter. 00278 */ 00279 _Pragma("_CRI suppress"); 00280 #endif 00281 /* 00282 * Ensure that *lck is written to memory before letting 00283 * another task read it. 00284 */ 00285 _cmr(); 00286 _semclr(TSKLK); 00287 } 00288 } 00289 00290 #pragma _CRI inline _inline_mtunlock 00291 static void 00292 _inline_mtunlock(plock_t *lck) 00293 { 00294 _semts(TSKLK); 00295 /* 00296 * Since lck's type has the "volatile" qualifier, the load of *lck will 00297 * bypass cache on CRAY TS. 00298 */ 00299 if ((*lck & ~SIGNBIT) != 0) { 00300 /* 00301 * Other tasks are waiting on the lock. Let _lockoff take 00302 * care of the details. 00303 */ 00304 _semclr(TSKLK); 00305 _lockoff(lck); 00306 } 00307 else { 00308 /* 00309 * Assure that any previous memory stores issued by this CPU 00310 * are complete before another CPU may obtain the lock. 00311 * Also, the lock word must be updated before release of the 00312 * semaphore because another task may be trying to queue 00313 * itself on this lock's waiting list. The _cmr() takes 00314 * care of both. 00315 */ 00316 *lck = 0; 00317 _cmr(); 00318 _semclr(TSKLK); 00319 } 00320 } 00321 00322 #endif /* _CRAY1 || _LIB_UMK */ 00323 00324 #undef SIGNBIT /* get rid of SIGNBIT definition */ 00325 00326 /* 00327 * KLUDGE - WORKAROUND - KLUDGE - WORKAROUND - KLUDGE -WORKAROUND 00328 * 00329 * This is a workaround for two C compiler bugs: 00330 * 00331 * SPR 80220 (fixed in SCC_M 4.0.2.5) 00332 * SPR 703732 (opened in March '97) 00333 * 00334 * Any module which includes cray/mtlock.h directly or indirectly and 00335 * does not contain any functions must invoke this macro to ensure that 00336 * a function exists in the C module. This seems to successfully 00337 * avoid the bug in the C compiler whereby a shared array is having 00338 * a shared array be incorrectly set up. 00339 */ 00340 #ifdef _CRAYT3D 00341 #define SHARED_CC_BUG_WORKAROUND(name) void name(void) {} 00342 #else 00343 #define SHARED_CC_BUG_WORKAROUND(name) 00344 #endif 00345 00346 #endif /* !_CRAY_MTLOCK_H */