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
+1
View File
@@ -763,6 +763,7 @@ GENHTML_OPT += --rc branch_coverage=1
GENHTML_OPT += --rc genhtml_hi_limit=100
GENHTML_OPT += --ignore-errors negative
GENHTML_OPT += --ignore-errors inconsistent
GENHTML_OPT += --ignore-errors empty
ifeq ($(COVERAGE_REF_BASE),)
GENHTML_OPT += --header-title "Code coverage for Verilator $(shell git describe --dirty)"
else
+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;
+1 -1
View File
@@ -22,6 +22,6 @@ cg7.cp.rev[0]: 1
cg7.cp.rev[1]: 0
cg8.cp.w[0]: 0
cg8.cp.w[1]: 1
cg9.__cross7.ok_x_lo [cross]: 1
cg9.__cross8.ok_x_lo [cross]: 1
cg9.cpA.ok: 1
cg9.cpB.lo: 1
+4 -4
View File
@@ -169,10 +169,10 @@ cg_trans.cp_v.v5: 2
cg_trans.cp_v.v6: 1
cg_trans.tx.t01_x_v5 [cross]: 1
cg_trans.tx.t01_x_v6 [cross]: 0
cg_unnamed_cross.__cross8.a0_x_read [cross]: 1
cg_unnamed_cross.__cross8.a0_x_write [cross]: 0
cg_unnamed_cross.__cross8.a1_x_read [cross]: 0
cg_unnamed_cross.__cross8.a1_x_write [cross]: 1
cg_unnamed_cross.__cross9.a0_x_read [cross]: 1
cg_unnamed_cross.__cross9.a0_x_write [cross]: 0
cg_unnamed_cross.__cross9.a1_x_read [cross]: 0
cg_unnamed_cross.__cross9.a1_x_write [cross]: 1
cg_unnamed_cross.cp_a.a0: 1
cg_unnamed_cross.cp_a.a1: 1
cg_unnamed_cross.cp_c.read: 1
+1 -1
View File
@@ -18,7 +18,7 @@ cg_cross_coverpoint_iff.cross_ab.one_x_one [cross]: 1
cg_cross_iff.cp_a.one: 3
cg_cross_iff.cp_b.one: 3
cg_cross_iff.cross_ab.one_x_one [cross]: 1
cg_cross_iff_unnamed.__cross7.one_x_one [cross]: 1
cg_cross_iff_unnamed.__cross8.one_x_one [cross]: 1
cg_cross_iff_unnamed.cp_a.one: 2
cg_cross_iff_unnamed.cp_b.one: 2
cg_default_iff.cp.def [default]: 1
+86 -62
View File
@@ -1228,64 +1228,9 @@ package Vt_debug_emitv___024unit;
disable label3;
end
endfunction
string __Venumtab_enum_name34[1:0];
string __Venumtab_enum_name36[1:0];
endpackage
package Vt_debug_emitv_std;
class Vt_debug_emitv_semaphore;
int signed m_keyCount;
int signed m_nextKeyCount;
m_nextKeyCount = 32'hffffffff;
longint m_ticket;
m_ticket = 64'h0;
longint m_nextTicket;
m_nextTicket = 64'h0;
function new;
input int signed keyCount;
m_keyCount = keyCount;
endfunction
task put;
input int signed keyCount;
m_keyCount = (m_keyCount + keyCount);
endtask
task get;
longint __Vincrement1;
input int signed keyCount;
longint ticket;
begin : label4
ticket = /*CRESET*/;
if (((m_keyCount >= keyCount) && (m_nextKeyCount
>
m_keyCount))) begin
begin
m_keyCount = (m_keyCount -
keyCount);
disable label4;
end
end
__Vincrement1 = m_nextTicket;
m_nextTicket = (m_nextTicket + 64'h1);
ticket = __Vincrement1;
wait((m_ticket == ticket));
m_nextKeyCount = keyCount;
wait((m_keyCount >= keyCount));
m_keyCount = (m_keyCount - keyCount);
m_ticket = (m_ticket + 64'h1);
end
endtask
function try_get;
input int signed keyCount;
begin : label5
try_get = /*CRESET*/;
if ((m_keyCount < keyCount)) begin
try_get = 'sh0;
disable label5;
end
m_keyCount = (m_keyCount - keyCount);
try_get = 'sh1;
disable label5;
end
endfunction
endclass
class Vt_debug_emitv_process;
typedef enum int signed{
FINISHED = 32'h0,
@@ -1297,12 +1242,12 @@ package Vt_debug_emitv_std;
VlProcessRef m_process;
function self;
Vt_debug_emitv_process pVt_debug_emitv_process;
begin : label6
begin : label4
self = /*CRESET*/;
p = new();
$c(p.m_process = vlProcess;);
self = p;
disable label6;
disable label4;
end
endfunction
task set_status;
@@ -1310,10 +1255,10 @@ package Vt_debug_emitv_std;
$c(m_process->state(s););
endtask
function status;
begin : label7
begin : label5
status = /*CRESET*/;
status = ($c(m_process->state()));
disable label7;
disable label5;
end
endfunction
task kill;
@@ -1385,12 +1330,12 @@ package Vt_debug_emitv_std;
???? // SYSTEMCSECTION
function get_randstate;
string s;
begin : label8
begin : label6
get_randstate = /*CRESET*/;
s = string'($c(0));
$c(s = m_process->randstate(););
get_randstate = s;
disable label8;
disable label6;
end
endfunction
task set_randstate;
@@ -1400,6 +1345,85 @@ package Vt_debug_emitv_std;
function new;
endfunction
process::FINISHEDprocess::KILLEDprocess::RUNNINGprocess::SUSPENDEDprocess::WAITINGendclass
class Vt_debug_emitv_semaphore;
typedef struct {
Vt_debug_emitv_process proc;
int signed reqKeys;
} procKeys;
struct {
Vt_debug_emitv_process proc;
int signed reqKeys;
} m_queue[$];
int signed m_keyCount;
task dropKilled;
while (((m_queue.size() > 'sh0) && (status()
==
process::
KILLED))) begin
m_queue.pop_front();
end
endtask
function new;
input int signed keyCount;
m_keyCount = keyCount;
endfunction
task put;
input int signed keyCount;
m_keyCount = (m_keyCount + keyCount);
endtask
task get;
input int signed keyCount;
begin : label7
dropKilled();
if (((m_keyCount >= keyCount) && ((
m_queue.size()
==
'sh0)
|| (m_queue.at(
'sh0).reqKeys
>
keyCount)))) begin
begin
m_keyCount = (m_keyCount -
keyCount);
disable label7;
end
end
m_queue.push_back(
???? // CONSPACKUORSTRUCT
???? // CONSPACKMEMBER
self()
???? // CONSPACKMEMBER
keyCount);
while ((m_queue.at('sh0).proc != self())) begin
begin
wait(((status() == process::
KILLED) || (m_queue.at(
'sh0).proc
== self())));
dropKilled();
end
end
wait((m_keyCount >= keyCount));
m_keyCount = (m_keyCount - keyCount);
m_queue.pop_front();
end
endtask
function try_get;
input int signed keyCount;
begin : label8
try_get = /*CRESET*/;
if ((m_keyCount < keyCount)) begin
try_get = 'sh0;
disable label8;
end
m_keyCount = (m_keyCount - keyCount);
try_get = 'sh1;
disable label8;
end
endfunction
endclass
function randomize;
randomize = 'sh0;
endfunction
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--binary"])
test.execute()
test.passes()
+37
View File
@@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0
module t;
semaphore sem = new(0);
process first_waiter;
process second_waiter;
bit acquired;
initial begin
fork
begin
first_waiter = process::self();
sem.get(1);
$stop;
end
begin
second_waiter = process::self();
sem.get(1);
acquired = 1;
end
join_none
wait (first_waiter != null && second_waiter != null);
#1;
first_waiter.kill();
sem.put(1);
#1;
if (!acquired) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
@@ -444,13 +444,13 @@
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.cp_c.read
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.cp_c.write
%000001 cross cp_a, cp_c; // no label: reported under the default cross name
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a0_x_read
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross9.a0_x_read
// cross: [a0, read]
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a0_x_write
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross9.a0_x_write
// cross: [a0, write]
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a1_x_read
-000000 point: type=covergroup comment= hier=cg_unnamed_cross.__cross9.a1_x_read
// cross: [a1, read]
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross8.a1_x_write
-000001 point: type=covergroup comment= hier=cg_unnamed_cross.__cross9.a1_x_write
// cross: [a1, write]
endgroup