2019-12-11
2019-12-11 22:30:51 by Stephen R. van den Berg <srb@cuci.nl>
-
c3317ce89f26bde330f331d82a0761c21928c5cb
(64 lines)
(+42/-22)
[
Show
| Annotate
]
Branch: 8.0
pgsql: Track back deadlock, explicitly release lock, speeds up code.
473: Inside #if defined(PG_DEBUGRACE)
PD("Nostash locked by %s\n",
describe_backtrace(nostash->current_locking_thread()->backtrace()));
#endif
- while (lock = (waitforreal ? nostash->lock : nostash->trylock)(1)) {
+ while (lock = (waitforreal > 0 ? nostash->lock : nostash->trylock)(1)) {
int mode;
if (sizeof(stash) && (mode = getstash(KEEP)) > KEEP)
sendcmd(mode); // Force out stash to the server
492:
return this;
#endif
}
- return bufcon(this)->start();
+ return !waitforreal && bufcon(this)->start();
}
private int write_cb() {
894:
{
Thread.MutexKey lock = closemux->lock();
if (_fetchlimit) {
- array reflock = ({ lock });
+ array reflock = ({ _fetchlimit = 0 });
+ for (;;) {
+ reflock[0] = lock;
lock = 0;
- _sendexecute(_fetchlimit = 0, reflock);
+ if (!_sendexecute(0, reflock)) {
+ lock = closemux->lock();
+ continue;
+ }
+ }
} else
lock = 0; // Force release before acquiring next
lock = _ddescribemux->lock();
1467:
private void replenishrows() {
if (_fetchlimit && datarows->size() <= _fetchlimit >> 1
&& _state >= COMMITTED) {
- Thread.MutexKey lock = closemux->lock();
+ Thread.MutexKey lock;
+ for (;;) {
+ lock = closemux->lock();
if (_fetchlimit) {
_fetchlimit = pgsqlsess._fetchlimit;
if (bytesreceived)
- _fetchlimit =
- min((portalbuffersize >> 1) * index / bytesreceived || 1, _fetchlimit);
+ _fetchlimit = min((portalbuffersize >> 1)
+ * index / bytesreceived || 1, _fetchlimit);
if (_fetchlimit)
if (inflight <= (_fetchlimit - 1) >> 1) {
array reflock = ({ lock });
lock = 0;
- _sendexecute(_fetchlimit, reflock);
+ if (!_sendexecute(_fetchlimit, reflock))
+ continue;
} else
PD("<%O _fetchlimit %d, inflight %d, skip execute\n",
_portalname, _fetchlimit, inflight);
}
-
+ break;
}
}
-
+ }
final void _processdataready(array datarow, void|int msglen) {
bytesreceived += msglen;
1522:
array(Thread.MutexKey) reflock = ({closemux->lock()});
if (!catch(plugbuffer = c->start()))
plugbuffer->sendcmd(_closeportal(plugbuffer, reflock));
- reflock = 0;
+ reflock[0] = 0;
if (_state < CLOSED) {
stmtifkey = 0;
_state = CLOSED;
1537:
};
}
- final void _sendexecute(int fetchlimit,
+ final int _sendexecute(int fetchlimit,
void|array(Thread.MutexKey)|bufcon|conxsess plugbuffer) {
int flushmode;
array(Thread.MutexKey) reflock;
1545:
fetchlimit, transtype);
if (arrayp(plugbuffer)) {
reflock = plugbuffer;
- plugbuffer = c->start(1);
+ if (!(plugbuffer = c->start(-1))) {
+ reflock[0] = 0;
+ return 0; // Found potential deadlock, release and try again
}
-
+ }
CHAIN(plugbuffer)->add_int8('E')->add_hstring(({_portalname, 0}), 4, 8)
->add_int32(fetchlimit);
if (!fetchlimit) {
1557:
} else
inflight += fetchlimit, flushmode = FLUSHSEND;
plugbuffer->sendcmd(flushmode, this);
+ if (reflock)
+ reflock[0] = 0;
+ return 1;
}
inline private array setuptimeout() {
1578:
//! @[eof()], @[send_row()]
/*semi*/final array(mixed) fetch_row() {
int|array datarow;
+ if (!this) // If object already destructed, return fast
+ return 0;
replenishrows();
if (arrayp(datarow = datarows->try_read()))
return datarow;