Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
mtlock.h
Go to the documentation of this file.
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines