Fix semaphore waiting on killed process (#8505)

Signed-off-by: Ryszard Rozak <[email protected]>
This commit is contained in:
Ryszard Rozak
2026-09-25 09:27:36 -04:00
committed by GitHub
parent ba8e0a1437
commit 765d05acf8
9 changed files with 202 additions and 112 deletions
+50 -40
View File
@@ -99,46 +99,6 @@ package std;
endfunction
endclass
// IEEE 1800-specified standard "semaphore"
class semaphore;
protected int m_keyCount;
protected int m_nextKeyCount = '1;
protected longint unsigned m_ticket = 0;
protected longint unsigned m_nextTicket = 0;
function new(int keyCount = 0);
m_keyCount = keyCount;
endfunction
function void put(int keyCount = 1);
m_keyCount += keyCount;
endfunction
task get(int keyCount = 1);
`ifdef VERILATOR_TIMING
longint unsigned ticket;
// Fast path: take if keys fit AND either no one is queued, or
// the head still doesn't fit (so we're not stealing its keys).
if (m_keyCount >= keyCount && m_nextKeyCount > m_keyCount) begin
m_keyCount -= keyCount;
return;
end
ticket = m_nextTicket++;
wait (m_ticket == ticket);
m_nextKeyCount = keyCount;
wait (m_keyCount >= keyCount);
m_keyCount -= keyCount;
m_ticket++;
`endif
endtask
function int try_get(int keyCount = 1);
if (m_keyCount < keyCount) return 0;
m_keyCount -= keyCount;
return 1;
endfunction
endclass
// IEEE 1800-specified standard "process"
class process;
typedef enum {
@@ -243,6 +203,56 @@ inline bool VlClassRef<`systemc_class_name>::operator<(const VlClassRef<`systemc
endfunction
endclass
// IEEE 1800-specified standard "semaphore"
class semaphore;
typedef struct {
process proc;
int reqKeys;
} procKeys;
procKeys m_queue[$];
protected int m_keyCount;
local task dropKilled;
// Drop killed processes from the queue
`ifdef VERILATOR_TIMING
while (m_queue.size() > 0 && m_queue[0].proc.status() == process::KILLED) m_queue.pop_front();
`endif
endtask
function new(int keyCount = 0);
m_keyCount = keyCount;
endfunction
function void put(int keyCount = 1);
m_keyCount += keyCount;
endfunction
task get(int keyCount = 1);
`ifdef VERILATOR_TIMING
dropKilled();
// Fast path: take if keys fit AND either no one is queued, or
// the head still doesn't fit (so we're not stealing its keys).
if (m_keyCount >= keyCount && (m_queue.size() == 0 || m_queue[0].reqKeys > keyCount)) begin
m_keyCount -= keyCount;
return;
end
m_queue.push_back('{process::self(), keyCount});
while (m_queue[0].proc != process::self()) begin
wait (m_queue[0].proc.status() == process::KILLED || m_queue[0].proc == process::self());
dropKilled();
end
wait (m_keyCount >= keyCount);
m_keyCount -= keyCount;
m_queue.pop_front();
`endif
endtask
function int try_get(int keyCount = 1);
if (m_keyCount < keyCount) return 0;
m_keyCount -= keyCount;
return 1;
endfunction
endclass
// IEEE 1800-specified standard "std::randomize"
function int randomize();
randomize = 0;