已合并
将load library时的mutex lock改为rdlock,提升并发性 #8160
totaj创建于 2025年7月28日
将load library时的mutex lock改为rdlock,提升并发性 #8160
已合并
totaj创建于 2025年7月28日
共 11 个文件变更+170-75
@@ -1959,10 +1959,10 @@ ObjectAddress ProcedureCreate(const char* procedureName, Oid procNamespace, Oid
1959 * To user-defined C_function, need rename library filename to special name,1959 * To user-defined C_function, need rename library filename to special name,
1960 * Because exist concurrent to the same library, so need lock.1960 * Because exist concurrent to the same library, so need lock.
1961 */1961 */
1962- AutoMutexLock libraryLock(&dlerror_lock);1962+ AutoRWLock libraryLock(&g_dlerror_lock_rw);
1963 1963 
1964 if (user_defined_c_fun) {1964 if (user_defined_c_fun) {
1965- libraryLock.lock();1965+ libraryLock.WrLock();
1966 1966 
1967 if ((IS_PGXC_COORDINATOR && !IsConnFromCoord()) || IS_SINGLE_NODE) {1967 if ((IS_PGXC_COORDINATOR && !IsConnFromCoord()) || IS_SINGLE_NODE) {
1968 /* Send library file to all node's $libdir/pg_plugin/ catalogue. */1968 /* Send library file to all node's $libdir/pg_plugin/ catalogue. */
@@ -2026,7 +2026,7 @@ ObjectAddress ProcedureCreate(const char* procedureName, Oid procNamespace, Oid
2026 }2026 }
2027 }2027 }
2028 if (user_defined_c_fun) {2028 if (user_defined_c_fun) {
2029- libraryLock.unLock();2029+ libraryLock.UnLock();
2030 }2030 }
2031 if (enable_plpgsql_gsdependency_guc() && !OidIsValid(propackageid)) {2031 if (enable_plpgsql_gsdependency_guc() && !OidIsValid(propackageid)) {
2032 if (u_sess->plsql_cxt.has_error) {2032 if (u_sess->plsql_cxt.has_error) {
@@ -2585,8 +2585,8 @@ void delete_file_handle(const char* library_path)
2585 DynamicFileList* file_scanner = NULL;2585 DynamicFileList* file_scanner = NULL;
2586 DynamicFileList* pre_file_scanner = file_list;2586 DynamicFileList* pre_file_scanner = file_list;
2587 2587 
2588- AutoMutexLock libraryLock(&file_list_lock);2588+ AutoRWLock libraryLock(&g_file_list_lock_rw);
2589- libraryLock.lock();2589+ libraryLock.WrLock();
2590 2590 
2591 char* fullname = expand_dynamic_library_name(library_path);2591 char* fullname = expand_dynamic_library_name(library_path);
2592 for (file_scanner = file_list; file_scanner != NULL; file_scanner = file_scanner->next) {2592 for (file_scanner = file_list; file_scanner != NULL; file_scanner = file_scanner->next) {
@@ -2611,7 +2611,7 @@ void delete_file_handle(const char* library_path)
2611 }2611 }
2612 }2612 }
2613 2613 
2614- libraryLock.unLock();2614+ libraryLock.UnLock();
2615}2615}
2616 2616 
2617/*2617/*
@@ -150,11 +150,11 @@ void load_file(const char* filename, bool restricted)
150 /* Unload the library if currently loaded */150 /* Unload the library if currently loaded */
151 internal_unload_library(fullname);151 internal_unload_library(fullname);
152 152 
153- AutoMutexLock libraryLock(&dlerror_lock);153+ AutoRWLock libraryLock(&g_dlerror_lock_rw);
154- libraryLock.lock();154+ libraryLock.WrLock();
155 /* Load the shared library */155 /* Load the shared library */
156 (void)internal_load_library(fullname);156 (void)internal_load_library(fullname);
157- libraryLock.unLock();157+ libraryLock.UnLock();
158 158 
159 pfree_ext(fullname);159 pfree_ext(fullname);
160}160}
@@ -175,8 +175,8 @@ void internal_delete_library()
175{175{
176 DynamicFileList* file_scanner = NULL;176 DynamicFileList* file_scanner = NULL;
177 177 
178- AutoMutexLock libraryLock(&file_list_lock);178+ AutoRWLock libraryLock(&g_file_list_lock_rw);
179- libraryLock.lock();179+ libraryLock.WrLock();
180 180 
181 while (file_list != NULL) {181 while (file_list != NULL) {
182 file_scanner = file_list;182 file_scanner = file_list;
@@ -195,7 +195,29 @@ void internal_delete_library()
195 file_scanner = NULL;195 file_scanner = NULL;
196 }196 }
197 file_list = file_tail = NULL;197 file_list = file_tail = NULL;
198- libraryLock.unLock();198+ libraryLock.UnLock();
199+}
200+ 
201+static DynamicFileList* get_file_scanner(const char* libname, struct stat* stat_buf)
202+{
203+ DynamicFileList* fs = NULL;
204+ /*
205+ * Scan the list of loaded FILES to see if the file has been loaded.
206+ */
207+ for (fs = file_list; fs != NULL && strcmp(libname, fs->filename) != 0; fs = fs->next) {}
208+ if (fs == NULL) {
209+ /*
210+ * Check for same files - different paths (ie, symlink or link)
211+ */
212+ if (stat(libname, stat_buf) == -1) {
213+ char* file = last_dir_separator(libname);
214+ file = (file == NULL) ? ((char*)libname) : (file + 1);
215+ ereport(ERROR, (errcode_for_file_access(), errmsg("could not access file \"%s\": %m", file)));
216+ }
217+ 
218+ for (fs = file_list; fs != NULL && !SAME_INODE(*stat_buf, *fs); fs = fs->next) {}
219+ }
220+ return fs;
199}221}
200 222 
201/*223/*
@@ -217,28 +239,21 @@ void* internal_load_library(const char* libname)
217 char* file = last_dir_separator(libname);239 char* file = last_dir_separator(libname);
218 file = (file == NULL) ? ((char*)libname) : (file + 1);240 file = (file == NULL) ? ((char*)libname) : (file + 1);
219 241 
220- PthreadMutexLock(t_thrd.utils_cxt.CurrentResourceOwner, &file_list_lock, true);242+ /* use read lock to check file_list first */
221- /*243+ PthreadRWlockRdlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
222- * Scan the list of loaded FILES to see if the file has been loaded.244+ file_scanner = get_file_scanner(libname, &stat_buf);
223- */
224- for (file_scanner = file_list; file_scanner != NULL && strcmp(libname, file_scanner->filename) != 0;
225- file_scanner = file_scanner->next)
226- ;
227- 
228 if (file_scanner == NULL) {245 if (file_scanner == NULL) {
229- /*246+ /* we don't have this library in file_list, so change to write lock to add us to file_list */
230- * Check for same files - different paths (ie, symlink or link)247+ ResourceOwnerForgetIfExistPthreadRWlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
231- */248+ PthreadRWlockWrlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
232- if (stat(libname, &stat_buf) == -1) {249+ /* double check after we got write lock, maybe it has been load by another thread */
233- ereport(ERROR, (errcode_for_file_access(), errmsg("could not access file \"%s\": %m", file)));250+ file_scanner = get_file_scanner(libname, &stat_buf);
251+ if (file_scanner != NULL) {
252+ /* other thread has added, we can change back to read lock and break */
253+ ResourceOwnerForgetIfExistPthreadRWlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
254+ PthreadRWlockRdlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
255+ goto file_scanner_not_null;
234 }256 }
235- 
236- for (file_scanner = file_list; file_scanner != NULL && !SAME_INODE(stat_buf, *file_scanner);
237- file_scanner = file_scanner->next)
238- ;
239- }
240- 
241- if (file_scanner == NULL) {
242 size_t tmplen = 0;257 size_t tmplen = 0;
243 errno_t rc = EOK;258 errno_t rc = EOK;
244 259 
@@ -249,7 +264,6 @@ void* internal_load_library(const char* libname)
249 264 
250 file_scanner = (DynamicFileList*)MemoryContextAlloc(265 file_scanner = (DynamicFileList*)MemoryContextAlloc(
251 INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), tmplen);266 INSTANCE_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), tmplen);
252- 
253 if (file_scanner == NULL) {267 if (file_scanner == NULL) {
254 ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory")));268 ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory")));
255 }269 }
@@ -294,7 +308,6 @@ void* internal_load_library(const char* libname)
294 }308 }
295#endif309#endif
296 file_scanner->handle = pg_dlopen(file_scanner->filename);310 file_scanner->handle = pg_dlopen(file_scanner->filename);
297- 
298 if (file_scanner->handle == NULL) {311 if (file_scanner->handle == NULL) {
299 char* load_error = NULL;312 char* load_error = NULL;
300 char error[DLERROR_MSG_MAX_LEN + 1];313 char error[DLERROR_MSG_MAX_LEN + 1];
@@ -316,7 +329,6 @@ void* internal_load_library(const char* libname)
316 329 
317 /* Check the magic function to determine compatibility */330 /* Check the magic function to determine compatibility */
318 magic_func = (PGModuleMagicFunction)pg_dlsym(file_scanner->handle, PG_MAGIC_FUNCTION_NAME_STRING);331 magic_func = (PGModuleMagicFunction)pg_dlsym(file_scanner->handle, PG_MAGIC_FUNCTION_NAME_STRING);
319- 
320 if (magic_func) {332 if (magic_func) {
321 const Pg_magic_struct* magic_data_ptr = (*magic_func)();333 const Pg_magic_struct* magic_data_ptr = (*magic_func)();
322 334 
@@ -367,8 +379,13 @@ void* internal_load_library(const char* libname)
367 file_tail->next = file_scanner;379 file_tail->next = file_scanner;
368 380 
369 file_tail = file_scanner;381 file_tail = file_scanner;
382+ 
383+ /* change file_list done, we can change back to read lock now */
384+ ResourceOwnerForgetIfExistPthreadRWlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
385+ PthreadRWlockRdlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
370 }386 }
371 387 
388+file_scanner_not_null:
372 /*389 /*
373 * check if the file_scanner has been registered390 * check if the file_scanner has been registered
374 */391 */
@@ -399,7 +416,7 @@ void* internal_load_library(const char* libname)
399 u_sess->fmgr_cxt.file_init_tail = file_init_scanner;416 u_sess->fmgr_cxt.file_init_tail = file_init_scanner;
400 }417 }
401 418 
402- ResourceOwnerForgetIfExistPthreadMutex(t_thrd.utils_cxt.CurrentResourceOwner, &file_list_lock, true);419+ ResourceOwnerForgetIfExistPthreadRWlock(t_thrd.utils_cxt.CurrentResourceOwner, &g_file_list_lock_rw);
403 420 
404 return file_scanner->handle;421 return file_scanner->handle;
405}422}
@@ -524,10 +541,10 @@ static void internal_unload_library(const char* libname)
524 * inode, else internal_load_library() will still think it's present.541 * inode, else internal_load_library() will still think it's present.
525 */542 */
526 543 
527- AutoMutexLock dlerrorLock(&dlerror_lock);544+ AutoRWLock dlerrorLock(&g_dlerror_lock_rw);
528- dlerrorLock.lock();545+ dlerrorLock.WrLock();
529- AutoMutexLock libraryLock(&file_list_lock);546+ AutoRWLock libraryLock(&g_file_list_lock_rw);
530- libraryLock.lock();547+ libraryLock.WrLock();
531 548 
532 for (file_scanner = file_list; file_scanner != NULL; file_scanner = nxt) {549 for (file_scanner = file_list; file_scanner != NULL; file_scanner = nxt) {
533 nxt = file_scanner->next;550 nxt = file_scanner->next;
@@ -557,8 +574,8 @@ static void internal_unload_library(const char* libname)
557 }574 }
558 }575 }
559 576 
560- libraryLock.unLock();577+ libraryLock.UnLock();
561- dlerrorLock.unLock();578+ dlerrorLock.UnLock();
562 579 
563#endif /* NOT_USED */580#endif /* NOT_USED */
564}581}
@@ -524,9 +524,8 @@ static void fmgr_info_C_lang(Oid functionId, FmgrInfo* finfo, HeapTuple procedur
524 LockDatabaseObject(ProcedureRelationId, functionId, 0, AccessShareLock);524 LockDatabaseObject(ProcedureRelationId, functionId, 0, AccessShareLock);
525 }525 }
526 526 
527- AutoMutexLock libraryLock(&dlerror_lock);527+ AutoRWLock libraryLock(&g_dlerror_lock_rw);
528- 528+ libraryLock.RdLock();
529- libraryLock.lock();
530 529 
531 /*530 /*
532 * We use function RunUdFFencedMode to replace if this UDF531 * We use function RunUdFFencedMode to replace if this UDF
@@ -539,10 +538,10 @@ static void fmgr_info_C_lang(Oid functionId, FmgrInfo* finfo, HeapTuple procedur
539 * See if we have the function address cached already538 * See if we have the function address cached already
540 */539 */
541 hashentry = lookup_C_func(procedureTuple);540 hashentry = lookup_C_func(procedureTuple);
542- 
543 if (hashentry != NULL) {541 if (hashentry != NULL) {
544 user_fn = hashentry->user_fn;542 user_fn = hashentry->user_fn;
545 inforec = hashentry->inforec;543 inforec = hashentry->inforec;
544+ libraryLock.UnLock();
546 } else {545 } else {
547 /* Look up the function itself */546 /* Look up the function itself */
548 if (strcmp(probinstring, "$libdir/plpgsql") && strcmp(probinstring, "$libdir/dist_fdw") &&547 if (strcmp(probinstring, "$libdir/plpgsql") && strcmp(probinstring, "$libdir/dist_fdw") &&
@@ -554,18 +553,31 @@ static void fmgr_info_C_lang(Oid functionId, FmgrInfo* finfo, HeapTuple procedur
554 strcmp(probinstring, "$libdir/mot_fdw")553 strcmp(probinstring, "$libdir/mot_fdw")
555#endif554#endif
556 ) {555 ) {
556+ /* change to write lock */
557+ libraryLock.UnLock();
558+ libraryLock.WrLock();
559+ hashentry = lookup_C_func(procedureTuple); /* double check */
560+ if (hashentry != NULL) {
561+ /* load by other thread, don't need lock anymore */
562+ user_fn = hashentry->user_fn;
563+ inforec = hashentry->inforec;
564+ libraryLock.UnLock();
565+ goto hashentry_not_null;
566+ }
557 funInfo = load_external_function(probinstring, prosrcstring, true, false);567 funInfo = load_external_function(probinstring, prosrcstring, true, false);
558 user_fn = funInfo.user_fn;568 user_fn = funInfo.user_fn;
559 inforec = funInfo.inforec;569 inforec = funInfo.inforec;
560 570 
561 /* Cache the addresses for later calls */571 /* Cache the addresses for later calls */
562 record_C_func(procedureTuple, user_fn, inforec);572 record_C_func(procedureTuple, user_fn, inforec);
573+ libraryLock.UnLock();
563 } else {574 } else {
575+ libraryLock.UnLock();
564 /* These function define in system codes, their version must be 1.*/576 /* These function define in system codes, their version must be 1.*/
565 user_fn = load_plpgsql_function(prosrcstring);577 user_fn = load_plpgsql_function(prosrcstring);
566 }578 }
567 }579 }
568- 580+hashentry_not_null:
569 switch (inforec->api_version) {581 switch (inforec->api_version) {
570 case 0:582 case 0:
571 case 1:583 case 1:
@@ -582,8 +594,6 @@ static void fmgr_info_C_lang(Oid functionId, FmgrInfo* finfo, HeapTuple procedur
582 594 
583 pfree_ext(probinstring);595 pfree_ext(probinstring);
584 pfree_ext(prosrcstring);596 pfree_ext(prosrcstring);
585- 
586- libraryLock.unLock();
587}597}
588 598 
589/*599/*
@@ -2876,8 +2876,8 @@ void PostgresInitializer::InitExtensionVariable()
2876 (void**)MemoryContextAllocZero(u_sess->self_mem_cxt, (Size)(initExtArraySize * sizeof(void*)));2876 (void**)MemoryContextAllocZero(u_sess->self_mem_cxt, (Size)(initExtArraySize * sizeof(void*)));
2877 2877 
2878 DynamicFileList* file_scanner = NULL;2878 DynamicFileList* file_scanner = NULL;
2879- AutoMutexLock libraryLock(&file_list_lock);2879+ AutoRWLock libraryLock(&g_file_list_lock_rw);
2880- libraryLock.lock();2880+ libraryLock.RdLock();
2881 2881 
2882 for (file_scanner = file_list; file_scanner != NULL; file_scanner = file_scanner->next) {2882 for (file_scanner = file_list; file_scanner != NULL; file_scanner = file_scanner->next) {
2883 /* 2883 /*
@@ -2889,7 +2889,7 @@ void PostgresInitializer::InitExtensionVariable()
2889 (*init_session_vars)(); /*It is assumed that this does not cause a deadlock for the file_list_lock*/2889 (*init_session_vars)(); /*It is assumed that this does not cause a deadlock for the file_list_lock*/
2890 }2890 }
2891 2891 
2892- libraryLock.unLock();2892+ libraryLock.UnLock();
2893 2893
2894 /* check whether the extension has been created 2894 /* check whether the extension has been created
2895 * at most one will be true.2895 * at most one will be true.
@@ -2163,6 +2163,27 @@ void ResourceOwnerForgetPthreadRWlock(ResourceOwner owner, pthread_rwlock_t* pRW
2163 errmsg("pthread rwlock is not owned by resource owner %s", owner->name)));2163 errmsg("pthread rwlock is not owned by resource owner %s", owner->name)));
2164}2164}
2165 2165 
2166+void ResourceOwnerForgetIfExistPthreadRWlock(ResourceOwner owner, pthread_rwlock_t* pRWlock)
2167+{
2168+ if (owner == NULL) {
2169+ return PthreadRWlockUnlock(owner, pRWlock);
2170+ }
2171+ pthread_rwlock_t** rwlocks = owner->pThdRWlocks;
2172+ int ns1 = owner->nPthreadRWlock - 1;
2173+ 
2174+ if (!owner->valid) {
2175+ return;
2176+ }
2177+ 
2178+ for (int i = ns1; i >= 0; i--) {
2179+ if (rwlocks[i] == pRWlock) {
2180+ PthreadRWlockUnlock(owner, pRWlock);
2181+ return;
2182+ }
2183+ }
2184+ return;
2185+}
2186+ 
2166int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace)2187int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace)
2167{2188{
2168 if (owner == NULL) {2189 if (owner == NULL) {
@@ -2170,11 +2191,11 @@ int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t*
2170 }2191 }
2171 pthread_mutex_t** mutexs = owner->pThdMutexs;2192 pthread_mutex_t** mutexs = owner->pThdMutexs;
2172 int ns1 = owner->nPthreadMutex - 1;2193 int ns1 = owner->nPthreadMutex - 1;
2173- 2194+ 
2174 if (!owner->valid) {2195 if (!owner->valid) {
2175 return 0;2196 return 0;
2176 }2197 }
2177- 2198+ 
2178 for (int i = ns1; i >= 0; i--) {2199 for (int i = ns1; i >= 0; i--) {
2179 if (mutexs[i] == pMutex) {2200 if (mutexs[i] == pMutex) {
2180 return PthreadMutexUnlock(owner, pMutex, trace);2201 return PthreadMutexUnlock(owner, pMutex, trace);
@@ -29,11 +29,10 @@
29 29 
30syscalllock getpwuid_lock;30syscalllock getpwuid_lock;
31syscalllock env_lock;31syscalllock env_lock;
32-syscalllock dlerror_lock;
33syscalllock kerberos_conn_lock;32syscalllock kerberos_conn_lock;
34syscalllock read_cipher_lock;33syscalllock read_cipher_lock;
35-syscalllock file_list_lock;34+pthread_rwlock_t g_file_list_lock_rw;
36- 35+pthread_rwlock_t g_dlerror_lock_rw;
37 36 
38/*37/*
39 * @Description: Atomic set val into *ptr in a 32-bit address, and return the previous pointed by ptr38 * @Description: Atomic set val into *ptr in a 32-bit address, and return the previous pointed by ptr
@@ -1680,8 +1680,8 @@ void libraryDoPendingDeletes(bool isCommit)
1680 * protect process variable file_list and CFuncHash, avoid they be1680 * protect process variable file_list and CFuncHash, avoid they be
1681 * concurrent changed of different thread.1681 * concurrent changed of different thread.
1682 */1682 */
1683- AutoMutexLock libraryLock(&dlerror_lock);1683+ AutoRWLock libraryLock(&g_dlerror_lock_rw);
1684- libraryLock.lock();1684+ libraryLock.WrLock();
1685 1685 
1686 ListCell* lc = NULL;1686 ListCell* lc = NULL;
1687 foreach (lc, u_sess->cmd_cxt.PendingLibraryDeletes) {1687 foreach (lc, u_sess->cmd_cxt.PendingLibraryDeletes) {
@@ -1698,7 +1698,7 @@ void libraryDoPendingDeletes(bool isCommit)
1698 1698 
1699 /* Reset PendingLibraryDeletes.*/1699 /* Reset PendingLibraryDeletes.*/
1700 ResetPendingLibraryDelete();1700 ResetPendingLibraryDelete();
1701- libraryLock.unLock();1701+ libraryLock.UnLock();
1702}1702}
1703 1703 
1704/*1704/*
@@ -586,8 +586,8 @@ static void syscall_lock_init(void)
586{586{
587 syscalllockInit(&getpwuid_lock);587 syscalllockInit(&getpwuid_lock);
588 syscalllockInit(&env_lock);588 syscalllockInit(&env_lock);
589- syscalllockInit(&dlerror_lock);
590 syscalllockInit(&kerberos_conn_lock);589 syscalllockInit(&kerberos_conn_lock);
591 syscalllockInit(&read_cipher_lock);590 syscalllockInit(&read_cipher_lock);
592- syscalllockInit(&file_list_lock);591+ pthread_rwlock_init(&g_file_list_lock_rw, NULL);
592+ pthread_rwlock_init(&g_dlerror_lock_rw, NULL);
593}593}
@@ -2780,8 +2780,8 @@ void parseAndRemoveLibrary(char *library, int nlibrary)
2780 errno_t rc = 0;2780 errno_t rc = 0;
2781 2781 
2782 /* Function delete_file_handle have change to process member, here need add lock. */2782 /* Function delete_file_handle have change to process member, here need add lock. */
2783- AutoMutexLock libraryLock(&dlerror_lock);2783+ AutoRWLock libraryLock(&g_dlerror_lock_rw);
2784- libraryLock.lock();2784+ libraryLock.WrLock();
2785 2785 
2786 while (nlib > 0) {2786 while (nlib > 0) {
2787 int libraryLen = 0;2787 int libraryLen = 0;
@@ -2802,7 +2802,7 @@ void parseAndRemoveLibrary(char *library, int nlibrary)
2802 nlib--;2802 nlib--;
2803 }2803 }
2804 2804 
2805- libraryLock.unLock();2805+ libraryLock.UnLock();
2806}2806}
2807 2807 
2808/*2808/*
@@ -739,6 +739,7 @@ extern Tuple ReplaceTupleNullCol(TupleDesc tupleDesc, TupleTableSlot* slot, bool
739 739 
740extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone);740extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone);
741extern int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace);741extern int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace);
742+extern void ResourceOwnerForgetIfExistPthreadRWlock(ResourceOwner owner, pthread_rwlock_t* pRWlock);
742 743 
743typedef bool (*replaceNullOrNotFunc)();744typedef bool (*replaceNullOrNotFunc)();
744 745 
@@ -764,9 +765,6 @@ public:
764 AutoMutexLock(pthread_mutex_t* mutex, bool trace = true)765 AutoMutexLock(pthread_mutex_t* mutex, bool trace = true)
765 : m_mutex(mutex), m_fLocked(false), m_trace(trace), m_owner(t_thrd.utils_cxt.CurrentResourceOwner)766 : m_mutex(mutex), m_fLocked(false), m_trace(trace), m_owner(t_thrd.utils_cxt.CurrentResourceOwner)
766 {767 {
767- if (mutex == &file_list_lock) {
768- m_owner = t_thrd.lsc_cxt.local_sysdb_resowner;
769- }
770 }768 }
771 769 
772 ~AutoMutexLock()770 ~AutoMutexLock()
@@ -814,11 +812,7 @@ public:
814 if (m_fLocked) {812 if (m_fLocked) {
815 int ret = 0;813 int ret = 0;
816 814 
817- if (m_mutex == &file_list_lock) {815+ ret = PthreadMutexUnlock(m_owner, m_mutex, m_trace);
818- ret = ResourceOwnerForgetIfExistPthreadMutex(m_owner, m_mutex, m_trace);
819- } else {
820- ret = PthreadMutexUnlock(m_owner, m_mutex, m_trace);
821- }
822 m_fLocked = (ret == 0 ? false : true);816 m_fLocked = (ret == 0 ? false : true);
823 if (m_fLocked) {817 if (m_fLocked) {
824 /* this should never happen, system may be completely in a mess */818 /* this should never happen, system may be completely in a mess */
@@ -841,6 +835,60 @@ private:
841 ResourceOwner m_owner;835 ResourceOwner m_owner;
842};836};
843 837 
838+class AutoRWLock {
839+public:
840+ AutoRWLock(pthread_rwlock_t* rwlock)
841+ : m_rwlock(rwlock), m_rdLocked(false), m_wrLocked(false), m_owner(t_thrd.utils_cxt.CurrentResourceOwner)
842+ {
843+ if (rwlock == &g_file_list_lock_rw) {
844+ m_owner = t_thrd.lsc_cxt.local_sysdb_resowner;
845+ }
846+ }
847+ 
848+ ~AutoRWLock()
849+ {
850+ UnLock();
851+ }
852+ 
853+ inline void RdLock()
854+ {
855+ // Guard against recursive lock, but we don't check rdlock and wrlock conflict
856+ if (!m_rdLocked) {
857+ PthreadRWlockRdlock(m_owner, m_rwlock);
858+ m_rdLocked = true;
859+ }
860+ }
861+ 
862+ inline void WrLock()
863+ {
864+ // Guard against recursive lock, but we don't check rdlock and wrlock conflict
865+ //
866+ if (!m_wrLocked) {
867+ PthreadRWlockWrlock(m_owner, m_rwlock);
868+ m_wrLocked = true;
869+ }
870+ }
871+ 
872+ inline void UnLock()
873+ {
874+ if (m_rdLocked || m_wrLocked) {
875+ if (m_rwlock == &g_file_list_lock_rw) {
876+ ResourceOwnerForgetIfExistPthreadRWlock(m_owner, m_rwlock);
877+ } else {
878+ PthreadRWlockUnlock(m_owner, m_rwlock);
879+ }
880+ m_rdLocked = false;
881+ m_wrLocked = false;
882+ }
883+ }
884+ 
885+private:
886+ pthread_rwlock_t* m_rwlock;
887+ bool m_rdLocked;
888+ bool m_wrLocked;
889+ ResourceOwner m_owner;
890+};
891+ 
844class AutoDopControl {892class AutoDopControl {
845public:893public:
846 AutoDopControl()894 AutoDopControl()
@@ -53,9 +53,9 @@ typedef pthread_mutex_t syscalllock;
53 */53 */
54extern syscalllock getpwuid_lock;54extern syscalllock getpwuid_lock;
55extern syscalllock env_lock;55extern syscalllock env_lock;
56-extern syscalllock dlerror_lock;
57extern syscalllock kerberos_conn_lock;56extern syscalllock kerberos_conn_lock;
58extern syscalllock read_cipher_lock;57extern syscalllock read_cipher_lock;
59-extern syscalllock file_list_lock;58+extern pthread_rwlock_t g_file_list_lock_rw;
59+extern pthread_rwlock_t g_dlerror_lock_rw;
60 60 
61#endif /* SYSCALL_LOCK_H_ */61#endif /* SYSCALL_LOCK_H_ */