Fix lock related crashes
This commit is contained in:
parent
4716d739e1
commit
59371d77ed
|
@ -37,13 +37,14 @@ DEVICE_READ32(PFIFO)
|
||||||
SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_CHID, d->pfifo.cache1.channel_id);
|
SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_CHID, d->pfifo.cache1.channel_id);
|
||||||
SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_MODE, d->pfifo.cache1.mode);
|
SET_MASK(result, NV_PFIFO_CACHE1_PUSH1_MODE, d->pfifo.cache1.mode);
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_STATUS:
|
case NV_PFIFO_CACHE1_STATUS: {
|
||||||
d->pfifo.cache1.cache_lock.lock();
|
std::unique_lock<std::mutex> cache_lock(d->pfifo.cache1.cache_lock);
|
||||||
|
|
||||||
if (d->pfifo.cache1.cache.empty()) {
|
if (d->pfifo.cache1.cache.empty()) {
|
||||||
result |= NV_PFIFO_CACHE1_STATUS_LOW_MARK; /* low mark empty */
|
result |= NV_PFIFO_CACHE1_STATUS_LOW_MARK; /* low mark empty */
|
||||||
}
|
}
|
||||||
d->pfifo.cache1.cache_lock.unlock();
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case NV_PFIFO_CACHE1_DMA_PUSH:
|
case NV_PFIFO_CACHE1_DMA_PUSH:
|
||||||
SET_MASK(result, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS,
|
SET_MASK(result, NV_PFIFO_CACHE1_DMA_PUSH_ACCESS,
|
||||||
d->pfifo.cache1.dma_push_enabled);
|
d->pfifo.cache1.dma_push_enabled);
|
||||||
|
@ -77,18 +78,18 @@ DEVICE_READ32(PFIFO)
|
||||||
result = d->pfifo.cache1.subroutine_return
|
result = d->pfifo.cache1.subroutine_return
|
||||||
| d->pfifo.cache1.subroutine_active;
|
| d->pfifo.cache1.subroutine_active;
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_PULL0:
|
case NV_PFIFO_CACHE1_PULL0: {
|
||||||
d->pfifo.cache1.cache_lock.lock();
|
std::unique_lock<std::mutex> cache_lock(d->pfifo.cache1.cache_lock);
|
||||||
result = d->pfifo.cache1.pull_enabled;
|
result = d->pfifo.cache1.pull_enabled;
|
||||||
d->pfifo.cache1.cache_lock.unlock();
|
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_ENGINE:
|
}
|
||||||
d->pfifo.cache1.cache_lock.lock();
|
case NV_PFIFO_CACHE1_ENGINE: {
|
||||||
|
std::unique_lock<std::mutex> cache_lock(d->pfifo.cache1.cache_lock);
|
||||||
for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) {
|
for (int i = 0; i < NV2A_NUM_SUBCHANNELS; i++) {
|
||||||
result |= d->pfifo.cache1.bound_engines[i] << (i * 2);
|
result |= d->pfifo.cache1.bound_engines[i] << (i * 2);
|
||||||
}
|
}
|
||||||
d->pfifo.cache1.cache_lock.unlock();
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
||||||
result = d->pfifo.cache1.dcount;
|
result = d->pfifo.cache1.dcount;
|
||||||
break;
|
break;
|
||||||
|
@ -169,27 +170,31 @@ DEVICE_WRITE32(PFIFO)
|
||||||
d->pfifo.cache1.subroutine_active =
|
d->pfifo.cache1.subroutine_active =
|
||||||
(value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE);
|
(value & NV_PFIFO_CACHE1_DMA_SUBROUTINE_STATE);
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_PULL0:
|
case NV_PFIFO_CACHE1_PULL0: {
|
||||||
d->pfifo.cache1.cache_lock.lock();
|
std::unique_lock<std::mutex> cache_lock(d->pfifo.cache1.cache_lock);
|
||||||
|
|
||||||
if ((value & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
if ((value & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
||||||
&& !d->pfifo.cache1.pull_enabled) {
|
&& !d->pfifo.cache1.pull_enabled) {
|
||||||
d->pfifo.cache1.pull_enabled = true;
|
d->pfifo.cache1.pull_enabled = true;
|
||||||
|
|
||||||
/* the puller thread should wake up */
|
/* the puller thread should wake up */
|
||||||
d->pfifo.cache1.cache_cond.notify_all();
|
d->pfifo.cache1.cache_cond.notify_all();
|
||||||
} else if (!(value & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
}
|
||||||
|
else if (!(value & NV_PFIFO_CACHE1_PULL0_ACCESS)
|
||||||
&& d->pfifo.cache1.pull_enabled) {
|
&& d->pfifo.cache1.pull_enabled) {
|
||||||
d->pfifo.cache1.pull_enabled = false;
|
d->pfifo.cache1.pull_enabled = false;
|
||||||
}
|
}
|
||||||
d->pfifo.cache1.cache_lock.unlock();
|
|
||||||
break;
|
break;
|
||||||
case NV_PFIFO_CACHE1_ENGINE:
|
}
|
||||||
d->pfifo.cache1.cache_lock.lock();
|
case NV_PFIFO_CACHE1_ENGINE: {
|
||||||
|
std::unique_lock<std::mutex> cache_lock(d->pfifo.cache1.cache_lock);
|
||||||
|
|
||||||
for (i = 0; i < NV2A_NUM_SUBCHANNELS; i++) {
|
for (i = 0; i < NV2A_NUM_SUBCHANNELS; i++) {
|
||||||
d->pfifo.cache1.bound_engines[i] = (FIFOEngine)((value >> (i * 2)) & 3);
|
d->pfifo.cache1.bound_engines[i] = (FIFOEngine)((value >> (i * 2)) & 3);
|
||||||
}
|
}
|
||||||
d->pfifo.cache1.cache_lock.unlock();
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
case NV_PFIFO_CACHE1_DMA_DCOUNT:
|
||||||
d->pfifo.cache1.dcount =
|
d->pfifo.cache1.dcount =
|
||||||
(value & NV_PFIFO_CACHE1_DMA_DCOUNT_VALUE);
|
(value & NV_PFIFO_CACHE1_DMA_DCOUNT_VALUE);
|
||||||
|
@ -270,10 +275,10 @@ static void pfifo_run_pusher(NV2AState *d) {
|
||||||
command->subchannel = state->subchannel;
|
command->subchannel = state->subchannel;
|
||||||
command->nonincreasing = state->method_nonincreasing;
|
command->nonincreasing = state->method_nonincreasing;
|
||||||
command->parameter = word;
|
command->parameter = word;
|
||||||
state->cache_lock.lock();
|
|
||||||
|
std::unique_lock<std::mutex> cache_lock(d->pfifo.cache1.cache_lock);
|
||||||
state->cache.push(command);
|
state->cache.push(command);
|
||||||
state->cache_cond.notify_all();
|
state->cache_cond.notify_all();
|
||||||
state->cache_lock.unlock();
|
|
||||||
|
|
||||||
if (!state->method_nonincreasing) {
|
if (!state->method_nonincreasing) {
|
||||||
state->method += 4;
|
state->method += 4;
|
||||||
|
@ -360,13 +365,14 @@ int pfifo_puller_thread(NV2AState *d)
|
||||||
glo_set_current(d->pgraph.gl_context);
|
glo_set_current(d->pgraph.gl_context);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::unique_lock<std::mutex> cache_lock(d->pfifo.cache1.cache_lock, std::defer_lock);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
state->cache_lock.lock();
|
|
||||||
while (state->cache.empty() || !state->pull_enabled) {
|
while (state->cache.empty() || !state->pull_enabled) {
|
||||||
state->cache_cond.wait(state->cache_lock);
|
state->cache_cond.wait(cache_lock);
|
||||||
|
|
||||||
if (d->exiting) {
|
if (d->exiting) {
|
||||||
state->cache_lock.unlock();
|
cache_lock.unlock();
|
||||||
#ifdef COMPILE_OPENGL
|
#ifdef COMPILE_OPENGL
|
||||||
glo_set_current(NULL);
|
glo_set_current(NULL);
|
||||||
#endif
|
#endif
|
||||||
|
@ -379,7 +385,7 @@ int pfifo_puller_thread(NV2AState *d)
|
||||||
state->working_cache.push(state->cache.front());
|
state->working_cache.push(state->cache.front());
|
||||||
state->cache.pop();
|
state->cache.pop();
|
||||||
}
|
}
|
||||||
state->cache_lock.unlock();
|
cache_lock.unlock();
|
||||||
|
|
||||||
d->pgraph.lock.lock();
|
d->pgraph.lock.lock();
|
||||||
|
|
||||||
|
@ -407,10 +413,10 @@ int pfifo_puller_thread(NV2AState *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the engine is bound to the subchannel */
|
/* the engine is bound to the subchannel */
|
||||||
state->cache_lock.lock();
|
cache_lock.lock();
|
||||||
state->bound_engines[command->subchannel] = entry.engine;
|
state->bound_engines[command->subchannel] = entry.engine;
|
||||||
state->last_engine = entry.engine;
|
state->last_engine = entry.engine;
|
||||||
state->cache_lock.unlock();
|
cache_lock.unlock();
|
||||||
} else if (command->method >= 0x100) {
|
} else if (command->method >= 0x100) {
|
||||||
/* method passed to engine */
|
/* method passed to engine */
|
||||||
|
|
||||||
|
|
|
@ -618,8 +618,6 @@ void CxbxReserveNV2AMemory(NV2AState *d)
|
||||||
NV2ADevice::NV2ADevice()
|
NV2ADevice::NV2ADevice()
|
||||||
{
|
{
|
||||||
m_nv2a_state = new NV2AState();
|
m_nv2a_state = new NV2AState();
|
||||||
|
|
||||||
m_nv2a_state->pfifo.cache1.cache_lock = std::unique_lock<std::mutex>(m_nv2a_state->pfifo.cache1._cache_lock, std::defer_lock);
|
|
||||||
pgraph_init(m_nv2a_state);
|
pgraph_init(m_nv2a_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -445,8 +445,7 @@ typedef struct Cache1State {
|
||||||
enum FIFOEngine last_engine;
|
enum FIFOEngine last_engine;
|
||||||
|
|
||||||
/* The actual command queue */
|
/* The actual command queue */
|
||||||
std::mutex _cache_lock;
|
std::mutex cache_lock;
|
||||||
std::unique_lock<std::mutex> cache_lock;
|
|
||||||
std::condition_variable cache_cond;
|
std::condition_variable cache_cond;
|
||||||
std::queue<CacheEntry*> cache;
|
std::queue<CacheEntry*> cache;
|
||||||
std::queue<CacheEntry*> working_cache;
|
std::queue<CacheEntry*> working_cache;
|
||||||
|
|
Loading…
Reference in New Issue