Skip to content

Commit 792caae

Browse files
committed
julec: add the --COMAXPROCS command-line argument to set a custom COMAXPROCS value
1 parent 95a64d6 commit 792caae

File tree

8 files changed

+76
-12
lines changed

8 files changed

+76
-12
lines changed

src/julec/compile.jule

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use "std/strings"
2424
let mut OutDir = "dist"
2525
let mut OutName = "ir.cpp"
2626
let mut Out = ""
27+
let mut COMAXPROCS = "default"
2728

2829
let targets = map[str][]str{
2930
"windows": ["amd64", "arm64", "i386"],
@@ -433,6 +434,24 @@ fn checkOptFlag(opt: str) {
433434
}
434435
}
435436

437+
fn checkCOMAXPROCS() {
438+
if COMAXPROCS == "default" {
439+
env::COMAXPROCS = 0
440+
ret
441+
}
442+
n := conv::ParseUint(COMAXPROCS, 10, 64) else {
443+
handle::Throw("--COMAXPROCS: value is not a valid number: " + COMAXPROCS)
444+
ret // Avoid error.
445+
}
446+
if n < 1 {
447+
handle::Throw("--COMAXPROCS: invalid value: " + COMAXPROCS)
448+
}
449+
if n > u64(i32.Max) {
450+
handle::Throw("--COMAXPROCS: value is too large: " + COMAXPROCS)
451+
}
452+
env::COMAXPROCS = i32(n)
453+
}
454+
436455
fn checkCppStdFlag() {
437456
match env::CppStd {
438457
| "cpp20":
@@ -448,6 +467,7 @@ fn checkFlags(args: []str): []str {
448467

449468
mut fs := flag::FlagSet.New()
450469

470+
fs.AddVar[str](unsafe { (&str)(&COMAXPROCS) }, "COMAXPROCS", 0, "Maximum number of Ps that can execute coroutines")
451471
fs.AddVar[str](unsafe { (&str)(&opt) }, "opt", 0, "Optimization level")
452472
fs.AddVar[str](unsafe { (&str)(&target) }, "target", 0, "Target system")
453473
fs.AddVar[str](unsafe { (&str)(&Out) }, "out", 'o', "Output identifier")
@@ -488,6 +508,7 @@ fn checkFlags(args: []str): []str {
488508
checkCppStdFlag()
489509
checkTargetFlag(target)
490510
checkOptFlag(opt)
511+
checkCOMAXPROCS()
491512

492513
ret content
493514
}

src/julec/env/compiler.jule

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,7 @@ let mut RC = true
2424
let mut Safety = true
2525

2626
// Production compilation.
27-
let mut Production = false
27+
let mut Production = false
28+
29+
// The comaxprocs value.
30+
let mut COMAXPROCS: i32 = 0

src/julec/main.jule

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,13 @@ The most common arguments are:
134134
architecture imititation and IR will be generated accordingly.
135135
But it will be compiled with your native target.
136136
Use the "julec tool targets" to see valid targets.
137-
The value "native-native" equals to your native target.`)
137+
The value "native-native" equals to your native target.
138+
--COMAXPROCS <value>
139+
Sets the maximum number of Ps that can execute coroutines concurrently.
140+
Pass "default" to explicitly use the runtime default.
141+
The value must be a valid integer and at least 1.
142+
The default may vary by machine and is a reasonable choice for most programs,
143+
optimized for overall concurrency.`)
138144
| CmdTest:
139145
println(`The test command compiles the packages named by the import paths for testing.
140146

@@ -179,7 +185,13 @@ The most common arguments are:
179185
architecture imititation and IR will be generated accordingly.
180186
But it will be compiled with your native target.
181187
Use the "julec tool targets" to see valid targets.
182-
The value "native-native" equals to your native target.`)
188+
The value "native-native" equals to your native target.
189+
--COMAXPROCS <value>
190+
Sets the maximum number of Ps that can execute coroutines concurrently.
191+
Pass "default" to explicitly use the runtime default.
192+
The value must be a valid integer and at least 1.
193+
The default may vary by machine and is a reasonable choice for most programs,
194+
optimized for overall concurrency.`)
183195
| CmdMod:
184196
println(`The mod command is a tool managing your jule modules.
185197

src/julec/obj/cxx/object.jule

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,6 +1581,7 @@ impl ObjectCoder {
15811581
v == meta::Program.Runtime.Qpcfreq ||
15821582
v == meta::Program.Runtime.Asynctime ||
15831583
v == meta::Program.Runtime.Blocking ||
1584+
v == meta::Program.Runtime.Comaxprocs ||
15841585
v == meta::Program.Runtime.TimebaseNumer ||
15851586
v == meta::Program.Runtime.TimebaseDenom {
15861587
continue
@@ -1641,11 +1642,19 @@ impl ObjectCoder {
16411642
__jule_envp = reinterpret_cast<__jule_U8**>(envp);
16421643

16431644
`)
1645+
// Initialize the "asynctime" runtime variable.
16441646
identCoder.var(&self.Buf, meta::Program.Runtime.Asynctime)
16451647
self.write(" = ")
16461648
self.ec.boolean(asyncRuntime)
16471649
self.write(";\n")
16481650
self.indent()
1651+
// Initialize the "comaxprocs" runtime variable.
1652+
identCoder.var(&self.Buf, meta::Program.Runtime.Comaxprocs)
1653+
self.write(" = ")
1654+
itoa(&self.Buf, i64(env::COMAXPROCS))
1655+
self.write(";\n")
1656+
self.indent()
1657+
16491658
identCoder.funcIns(&self.Buf, meta::Program.Runtime.Init)
16501659
self.write("();\n\n")
16511660
self.initGlobals()

src/julec/obj/meta/meta.jule

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ struct Runtime {
4141
Sched: &sema::Var
4242
Asynctime: &sema::Var
4343
Blocking: &sema::Var
44+
Comaxprocs: &sema::Var
4445
TimebaseNumer: &sema::Var // Darwin
4546
TimebaseDenom: &sema::Var // Darwin
4647
Kq: &sema::Var // Darwin
@@ -141,6 +142,7 @@ fn CollectRuntime(mut ir: &obj::IR): &Runtime {
141142
meta.Sched = obj::RuntimeFindGlobal(p, "sched")
142143
meta.Asynctime = obj::RuntimeFindGlobal(p, "asynctime")
143144
meta.Blocking = obj::RuntimeFindGlobal(p, "blocking")
145+
meta.Comaxprocs = obj::RuntimeFindGlobal(p, "comaxprocs")
144146
meta.TimebaseNumer = p.FindVar("timebaseNumer", false) // Darwin
145147
meta.TimebaseDenom = p.FindVar("timebaseDenom", false) // Darwin
146148
meta.Kq = p.FindVar("kq", false) // Darwin

std/runtime/proc.jule

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,13 @@ extern fn __jule_trampolineRun()
178178
// Calls schedthread with P.
179179
extern let __jule_trampoline_schedthread: *unsafe
180180

181+
// The value of the COMAXPROCS.
182+
// Compiler will set it to zero for default value, which is initialized by runtime.
183+
// Otherwise, this is initialized by the compiler to a custom value before runtime initialized.
184+
let mut comaxprocs: i32 = 0
185+
181186
// Returns the maximum number of CPUs that can be executing simultaneously.
182-
fn COMAXPROCS(): int { ret numcpu }
187+
fn COMAXPROCS(): int { ret int(comaxprocs) }
183188

184189
const (
185190
// The maximum count of the runnable coroutine queue of a P.
@@ -909,7 +914,7 @@ top:
909914
//
910915
// Stealing is limited to a small fixed number of attempts to
911916
// avoid excessive contention and cache thrashing.
912-
if m.spinning || 2*atomic::Load(&sched.nmspinning, atomic::Relaxed) < i32(COMAXPROCS())-atomic::Load(&sched.npidle, atomic::Relaxed) {
917+
if m.spinning || 2*atomic::Load(&sched.nmspinning, atomic::Relaxed) < comaxprocs-atomic::Load(&sched.npidle, atomic::Relaxed) {
913918
if !m.spinning {
914919
becomeSpinning(m)
915920
}
@@ -1255,6 +1260,13 @@ async fn yield() {
12551260
park2(&m.c, tg, reasonNA).await
12561261
}
12571262

1263+
fn asynctimeinit() {
1264+
// Initialize the comaxprocs variable.
1265+
if comaxprocs == 0 {
1266+
comaxprocs = i32(numcpu)
1267+
}
1268+
}
1269+
12581270
#disable nilptr boundary
12591271
fn schedinit() {
12601272
// Initialize the global scheduler instance.
@@ -1266,7 +1278,7 @@ fn schedinit() {
12661278
// Because we are in the program initialize state, no concurrency risk.
12671279

12681280
// Initialize Ps.
1269-
maxprocs := i32(COMAXPROCS())
1281+
maxprocs := comaxprocs
12701282
sched.allp = make([]&p, maxprocs)
12711283
sched.npidle = maxprocs - sched.nm
12721284
mut i := i32(0)
@@ -1329,6 +1341,11 @@ fn sysmon() {
13291341
}
13301342
}
13311343

1344+
fn sysmoninit() {
1345+
// Start the sysmon thread.
1346+
unsafe { threadSpawn((*unsafe)(uintptr(sysmon)), nil) }
1347+
}
1348+
13321349
// Schedules some M to run the P (creates an M if necessary).
13331350
// If P==nil, the behavior is undefined. P is always should be a valid pointer.
13341351
// If spinning is set, the caller has incremented nmspinning and must provide a

std/runtime/runtime.jule

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ fn __init() {
2727
// And globally initialized map values ​​will use different hashes.
2828
// Same key may not match, avoid this implementation mistake.
2929
hashinit()
30+
// Initialize the common asynctime.
31+
// This funtion inititializes only commons for sync and async runtime.
32+
// Such as COMAXPROCS, which may be used by sync runtime.
33+
asynctimeinit()
34+
// Initialize the asynctime specifics.
3035
if asynctime {
3136
// Initialize thread pool for blocking jobs.
3237
blockinginit()
@@ -37,9 +42,4 @@ fn __init() {
3742
// Initialize and start sysmon.
3843
sysmoninit()
3944
}
40-
}
41-
42-
// Starts the sysmon thread.
43-
fn sysmoninit() {
44-
unsafe { threadSpawn((*unsafe)(uintptr(sysmon)), nil) }
4545
}

std/sync/waitgroup.jule

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use "std/sync/atomic"
99
// The main coroutine calls [WaitGroup.Add] to set the number of
1010
// coroutines to wait for. Then each of the coroutines runs and
1111
// calls [WaitGroup.Done] when finished. At the same time,
12-
// [WaitGroup.Wait] can be used to block until all goroutines have finished.
12+
// [WaitGroup.Wait] can be used to block until all coroutines have finished.
1313
//
1414
// A WaitGroup must not be copied after first use.
1515
struct WaitGroup {

0 commit comments

Comments
 (0)