notify the system that a thread needs to wait for another thread called by a *waiter* to declare that it (thd) will wait for another thread (blocker) on a specific resource (resid). can be called many times, if many blockers own a blocking resource. but must always be called with the same resource id - a thread cannot wait for more than one resource at a time. @return WT_OK or WT_DEA
| 1009 | performed for this new edge. |
| 1010 | */ |
| 1011 | int wt_thd_will_wait_for(WT_THD *thd, WT_THD *blocker, |
| 1012 | const WT_RESOURCE_ID *resid) |
| 1013 | { |
| 1014 | uint i; |
| 1015 | WT_RESOURCE *rc; |
| 1016 | DBUG_ENTER("wt_thd_will_wait_for"); |
| 1017 | |
| 1018 | LF_REQUIRE_PINS(3); |
| 1019 | |
| 1020 | DBUG_PRINT("wt", ("enter: thd=%s, blocker=%s, resid=%lu", |
| 1021 | thd->name, blocker->name, (ulong)resid->value)); |
| 1022 | |
| 1023 | if (fix_thd_pins(thd)) |
| 1024 | DBUG_RETURN(WT_DEADLOCK); |
| 1025 | |
| 1026 | if (thd->waiting_for == 0) |
| 1027 | { |
| 1028 | uint keylen; |
| 1029 | const void *key; |
| 1030 | /* XXX if (restype->make_key) key= restype->make_key(resid, &keylen); else */ |
| 1031 | { |
| 1032 | key= resid; |
| 1033 | keylen= sizeof_WT_RESOURCE_ID; |
| 1034 | } |
| 1035 | |
| 1036 | DBUG_PRINT("wt", ("first blocker")); |
| 1037 | |
| 1038 | retry: |
| 1039 | while ((rc= lf_hash_search(&reshash, thd->pins, key, keylen)) == 0) |
| 1040 | { |
| 1041 | WT_RESOURCE tmp; |
| 1042 | |
| 1043 | DBUG_PRINT("wt", ("failed to find rc in hash, inserting")); |
| 1044 | memset(&tmp, 0, sizeof(tmp)); |
| 1045 | tmp.id= *resid; |
| 1046 | tmp.state= ACTIVE; |
| 1047 | |
| 1048 | if (lf_hash_insert(&reshash, thd->pins, &tmp) == -1) /* if OOM */ |
| 1049 | DBUG_RETURN(WT_DEADLOCK); |
| 1050 | /* |
| 1051 | Two cases: either lf_hash_insert() failed - because another thread |
| 1052 | has just inserted a resource with the same id - and we need to retry. |
| 1053 | Or lf_hash_insert() succeeded, and then we need to repeat |
| 1054 | lf_hash_search() to find a real address of the newly inserted element. |
| 1055 | That is, we don't care what lf_hash_insert() has returned. |
| 1056 | And we need to repeat the loop anyway. |
| 1057 | */ |
| 1058 | } |
| 1059 | if (rc == MY_ERRPTR) |
| 1060 | DBUG_RETURN(WT_DEADLOCK); |
| 1061 | |
| 1062 | DBUG_PRINT("wt", ("found in hash rc=%p", rc)); |
| 1063 | |
| 1064 | rc_wrlock(rc); |
| 1065 | if (rc->state != ACTIVE) |
| 1066 | { |
| 1067 | DBUG_PRINT("wt", ("but it's not active, retrying")); |
| 1068 | /* Somebody has freed the element while we weren't looking */ |
nothing calls this directly
no test coverage detected