@@ -120,7 +120,8 @@ static void worker_loop(void* arg) {
120120 * ray_pool_create
121121 * -------------------------------------------------------------------------- */
122122
123- ray_err_t ray_pool_create (ray_pool_t * pool , uint32_t n_workers ) {
123+ static ray_err_t ray_pool_create_impl (ray_pool_t * pool , uint32_t n_workers ,
124+ bool auto_size ) {
124125 /* conc-L7: memset zeroes all fields including the `cancelled` atomic,
125126 * which resets any cancellation state from a prior pool instance. */
126127 memset (pool , 0 , sizeof (* pool ));
@@ -133,14 +134,14 @@ ray_err_t ray_pool_create(ray_pool_t* pool, uint32_t n_workers) {
133134 atomic_init (& pool -> pending , 0 );
134135 atomic_init (& pool -> cancelled , 0 );
135136
136- if (n_workers == 0 ) {
137+ if (auto_size ) {
137138 /* Auto-size to ncpu-1. The RAYFORCE_CORES env var overrides this
138139 * default worker count — the test harness sets it (see the Makefile
139140 * `test` target) so neither the in-process runtime nor the server
140141 * children it spawns via .sys.exec each create ncpu-1 threads on a
141- * many-core box. An explicit -c (which passes n_workers > 0 through
142- * ray_pool_init) bypasses this entirely, and a non-test run with the
143- * var unset keeps the historical ncpu-1 default. */
142+ * many-core box. An explicit positive -c uses ray_pool_init_total()
143+ * with exact sizing and bypasses this entirely; a non-test run with
144+ * the var unset keeps the historical ncpu-1 default. */
144145 const char * env = getenv ("RAYFORCE_CORES" );
145146 if (env && * env ) {
146147 long v = strtol (env , NULL , 10 );
@@ -221,6 +222,10 @@ ray_err_t ray_pool_create(ray_pool_t* pool, uint32_t n_workers) {
221222 return RAY_OK ;
222223}
223224
225+ ray_err_t ray_pool_create (ray_pool_t * pool , uint32_t n_workers ) {
226+ return ray_pool_create_impl (pool , n_workers , n_workers == 0 );
227+ }
228+
224229/* --------------------------------------------------------------------------
225230 * ray_pool_free
226231 * -------------------------------------------------------------------------- */
@@ -506,11 +511,11 @@ ray_pool_t* ray_pool_get(void) {
506511 * Public API wrappers (declared in rayforce.h)
507512 * -------------------------------------------------------------------------- */
508513
509- /* conc-L4: If ray_pool_init() is called when the pool is already initialized
510- * (state==2), the n_workers parameter is silently ignored and the existing
511- * pool configuration is preserved. This is by design — the pool is a
512- * singleton and reconfiguration requires ray_pool_destroy() + ray_pool_init() . */
513- ray_err_t ray_pool_init (uint32_t n_workers ) {
514+ /* conc-L4: If an initializer is called when the pool is already initialized
515+ * (state==2), its requested size is silently ignored and the existing pool
516+ * configuration is preserved. This is by design — the pool is a singleton
517+ * and reconfiguration requires ray_pool_destroy() followed by initialization . */
518+ static ray_err_t ray_pool_init_impl (uint32_t n_workers , bool auto_size ) {
514519 uint32_t expected = 0 ;
515520 if (!atomic_compare_exchange_strong_explicit (& g_pool_init_state , & expected , 1 ,
516521 memory_order_acq_rel ,
@@ -527,7 +532,7 @@ ray_err_t ray_pool_init(uint32_t n_workers) {
527532 }
528533 return RAY_OK ; /* already initialized or completed during our spin */
529534 }
530- ray_err_t err = ray_pool_create (& g_pool , n_workers );
535+ ray_err_t err = ray_pool_create_impl (& g_pool , n_workers , auto_size );
531536 if (err == RAY_OK ) {
532537 atomic_store_explicit (& g_pool_init_state , 2 , memory_order_release );
533538 } else {
@@ -536,6 +541,16 @@ ray_err_t ray_pool_init(uint32_t n_workers) {
536541 return err ;
537542}
538543
544+ ray_err_t ray_pool_init (uint32_t n_workers ) {
545+ return ray_pool_init_impl (n_workers , n_workers == 0 );
546+ }
547+
548+ ray_err_t ray_pool_init_total (uint32_t total_workers ) {
549+ if (total_workers == 0 )
550+ return ray_pool_init_impl (0 , true);
551+ return ray_pool_init_impl (total_workers - 1 , false);
552+ }
553+
539554void ray_pool_destroy (void ) {
540555 uint32_t expected = 2 ;
541556 if (!atomic_compare_exchange_strong_explicit (& g_pool_init_state , & expected , 3 ,
0 commit comments