已合并
将load library时的mutex lock改为rdlock,提升并发性 #8160
totaj创建于 2025年7月28日
将load library时的mutex lock改为rdlock,提升并发性 #8160
已合并
共 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 | #endif | 309 | #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 registered | 390 | * 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 UDF | 531 | * 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 already | 538 | * 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 | #endif | 554 | #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 | + | ||
| 2166 | int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace) | 2187 | int 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 | ||
| 30 | syscalllock getpwuid_lock; | 30 | syscalllock getpwuid_lock; |
| 31 | syscalllock env_lock; | 31 | syscalllock env_lock; |
| 32 | -syscalllock dlerror_lock; | ||
| 33 | syscalllock kerberos_conn_lock; | 32 | syscalllock kerberos_conn_lock; |
| 34 | syscalllock read_cipher_lock; | 33 | syscalllock 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 ptr | 38 | * @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 be | 1680 | * 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 | ||
| 740 | extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone); | 740 | extern Datum ExecEvalArrayRef(ArrayRefExprState* astate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone); |
| 741 | extern int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace); | 741 | extern int ResourceOwnerForgetIfExistPthreadMutex(ResourceOwner owner, pthread_mutex_t* pMutex, bool trace); |
| 742 | +extern void ResourceOwnerForgetIfExistPthreadRWlock(ResourceOwner owner, pthread_rwlock_t* pRWlock); | ||
| 742 | 743 | ||
| 743 | typedef bool (*replaceNullOrNotFunc)(); | 744 | typedef 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 | + | ||
| 844 | class AutoDopControl { | 892 | class AutoDopControl { |
| 845 | public: | 893 | public: |
| 846 | AutoDopControl() | 894 | AutoDopControl() |
| @@ -53,9 +53,9 @@ typedef pthread_mutex_t syscalllock; | |||
| 53 | */ | 53 | */ |
| 54 | extern syscalllock getpwuid_lock; | 54 | extern syscalllock getpwuid_lock; |
| 55 | extern syscalllock env_lock; | 55 | extern syscalllock env_lock; |
| 56 | -extern syscalllock dlerror_lock; | ||
| 57 | extern syscalllock kerberos_conn_lock; | 56 | extern syscalllock kerberos_conn_lock; |
| 58 | extern syscalllock read_cipher_lock; | 57 | extern 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_ */ |