00001 /* 00002 00003 OpenMP runtime library to be used in conjunction with Open64 Compiler Suites. 00004 00005 Copyright (C) 2003 - 2009 Tsinghua University. 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Lesser General Public 00009 License as published by the Free Software Foundation; either 00010 version 2.1 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public 00018 License along with this library; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 00021 Contact information: HPC Institute, Department of Computer Science and Technology, 00022 Tsinghua University, Beijing 100084, CHINA, or: 00023 00024 http://hpc.cs.tsinghua.edu.cn 00025 00026 */ 00027 00028 /* 00029 * File: omp_lock.c 00030 * Abstract: implementation of OpenMP lock and critical sections 00031 * History: 04/23/2003, built by Jiang Hongshan, Tsinghua Univ. 00032 * 06/09/2005, updated by Liao Chunhua, Univ. of Houston 00033 * 00034 */ 00035 00036 #include <stdlib.h> 00037 #include "omp_lock.h" 00038 #include "omp_rtl.h" 00039 #include "omp_sys.h" 00040 00041 static ompc_lock_t atomic_lock; 00042 00043 00044 inline void 00045 __ompc_init_lock (volatile ompc_lock_t *lp) 00046 { 00047 pthread_mutex_init((pthread_mutex_t *)lp, NULL); 00048 } 00049 00050 00051 inline void 00052 __ompc_lock (volatile ompc_lock_t *lp) 00053 { 00054 pthread_mutex_lock((pthread_mutex_t *)lp); 00055 } 00056 00057 00058 inline void 00059 __ompc_unlock (volatile ompc_lock_t *lp) 00060 { 00061 pthread_mutex_unlock((pthread_mutex_t *)lp); 00062 } 00063 00064 00065 inline void 00066 __ompc_destroy_lock (volatile ompc_lock_t *lp) 00067 { 00068 pthread_mutex_destroy((pthread_mutex_t *)lp); 00069 } 00070 00071 00072 inline int 00073 __ompc_test_lock (volatile ompc_lock_t *lp) 00074 { 00075 return (pthread_mutex_trylock((pthread_mutex_t *)lp) == 0); 00076 } 00077 00078 00079 void 00080 __ompc_init_nest_lock (volatile ompc_nest_lock_t *lp) 00081 { 00082 __ompc_init_lock (&lp->lock); 00083 __ompc_init_lock (&lp->wait); 00084 lp->count = 0; 00085 } 00086 00087 00088 void 00089 __ompc_nest_lock (volatile ompc_nest_lock_t *lp) 00090 { 00091 pthread_t id = pthread_self(); 00092 int nest; 00093 00094 if( (lp->count > 0) && (lp->thread_id == id) ) { 00095 nest = 1; 00096 } else { 00097 wait_nest_lock: 00098 __ompc_lock(&lp->wait); /* be blocked here */ 00099 nest = 0; 00100 } 00101 __ompc_lock(&lp->lock); 00102 if(nest) { 00103 if( lp->count == 0 ) { /* the 'wait' lock be released */ 00104 if(!__ompc_test_lock(&lp->wait)) { 00105 __ompc_unlock(&lp->lock); 00106 goto wait_nest_lock; 00107 } 00108 lp->thread_id = id; 00109 } else { /* lp->count > 0 */ 00110 if(lp->thread_id != id) { 00111 __ompc_unlock(&lp->lock); 00112 goto wait_nest_lock; 00113 } 00114 } 00115 lp->count++; 00116 } else { /* get the 'wait' lock. Assert:( lp->count == 0 ) */ 00117 lp->thread_id = id; 00118 lp->count = 1; 00119 } 00120 __ompc_unlock(&lp->lock); 00121 } 00122 00123 00124 void 00125 __ompc_nest_unlock (volatile ompc_nest_lock_t *lp) 00126 { 00127 __ompc_lock (&lp->lock); 00128 if(lp->count > 0){ 00129 lp->count--; 00130 if(lp->count == 0){ 00131 __ompc_unlock(&lp->wait); 00132 } 00133 } 00134 __ompc_unlock (&lp->lock); 00135 } 00136 00137 00138 void 00139 __ompc_destroy_nest_lock (volatile ompc_nest_lock_t *lp) 00140 { 00141 __ompc_destroy_lock (&lp->wait); 00142 __ompc_destroy_lock (&lp->lock); 00143 } 00144 00145 00146 int 00147 __ompc_test_nest_lock (volatile ompc_nest_lock_t *lp) 00148 { 00149 pthread_t id = pthread_self(); 00150 00151 __ompc_lock(&lp->lock); 00152 if(lp->count > 0){ 00153 if(lp->thread_id == id){ 00154 lp->count++; 00155 } 00156 else{ 00157 __ompc_unlock(&lp->lock); 00158 return 0; 00159 } 00160 } 00161 else{ 00162 if(!__ompc_test_lock(&lp->wait)){ 00163 __ompc_unlock(&lp->lock); 00164 return 0; 00165 } 00166 lp->thread_id = id; 00167 lp->count = 1; 00168 } 00169 __ompc_unlock(&lp->lock); 00170 return lp->count; 00171 } 00172 00173 /* for Critical directive */ 00174 /*Changed by Liao, the work of init lock has been moved to runtime */ 00175 00176 inline void 00177 __ompc_critical(int gtid, volatile ompc_lock_t **lck) 00178 { 00179 if (*lck ==NULL) { 00180 __ompc_lock(&_ompc_thread_lock); 00181 if ((ompc_lock_t*)*lck == NULL){ 00182 *lck = (ompc_lock_t *)malloc(sizeof(ompc_lock_t)); 00183 Is_True(*lck!=NULL, 00184 ("Cannot allocate lock memory for critical")); 00185 } 00186 __ompc_init_lock (*lck); 00187 __ompc_unlock (&_ompc_thread_lock); 00188 } 00189 __ompc_lock((volatile ompc_lock_t *)*lck); 00190 } 00191 00192 inline void 00193 __ompc_end_critical(int gtid, volatile ompc_lock_t **lck) 00194 { 00195 __ompc_unlock((volatile ompc_lock_t *)*lck); 00196 } 00197 00198 00199 inline void 00200 __ompc_critical_light(int gtid, volatile ompc_lock_t **lck) 00201 { 00202 __ompc_spin_lock((void*)lck); 00203 } 00204 00205 inline void 00206 __ompc_end_critical_light(int gtid, volatile ompc_lock_t **lck) 00207 { 00208 __ompc_spin_unlock((void*)lck); 00209 }
1.5.6