@@ -6881,6 +6881,132 @@ static ERL_NIF_TERM nif_owngil_destroy_session(ErlNifEnv *env, int argc,
68816881 return ATOM_OK ;
68826882}
68836883
6884+ /**
6885+ * @brief NIF: Apply imports to OWN_GIL session
6886+ *
6887+ * Imports modules into the worker's sys.modules.
6888+ * Args: WorkerId, HandleId, Imports (list of {ModuleBin, FuncBin | all})
6889+ */
6890+ static ERL_NIF_TERM nif_owngil_apply_imports (ErlNifEnv * env , int argc ,
6891+ const ERL_NIF_TERM argv []) {
6892+ if (argc != 3 ) {
6893+ return enif_make_badarg (env );
6894+ }
6895+
6896+ if (!subinterp_thread_pool_is_ready ()) {
6897+ return ATOM_OK ; /* Silently succeed if pool not ready */
6898+ }
6899+
6900+ unsigned int worker_id ;
6901+ ErlNifUInt64 handle_id ;
6902+
6903+ if (!enif_get_uint (env , argv [0 ], & worker_id ) ||
6904+ !enif_get_uint64 (env , argv [1 ], & handle_id )) {
6905+ return enif_make_badarg (env );
6906+ }
6907+
6908+ if (worker_id >= (unsigned int )g_thread_pool .num_workers ) {
6909+ return ATOM_OK ; /* Invalid worker, silently succeed */
6910+ }
6911+
6912+ /* Serialize imports list to ETF */
6913+ ErlNifBinary payload_bin ;
6914+ if (!enif_term_to_binary (env , argv [2 ], & payload_bin )) {
6915+ return ATOM_OK ; /* Serialization failed, silently succeed */
6916+ }
6917+
6918+ subinterp_thread_worker_t * w = & g_thread_pool .workers [worker_id ];
6919+
6920+ pthread_mutex_lock (& w -> dispatch_mutex );
6921+
6922+ uint64_t request_id = atomic_fetch_add (& g_thread_pool .next_request_id , 1 );
6923+ owngil_header_t header = {
6924+ .magic = OWNGIL_MAGIC ,
6925+ .version = OWNGIL_PROTOCOL_VERSION ,
6926+ .msg_type = MSG_REQUEST ,
6927+ .req_type = REQ_APPLY_IMPORTS ,
6928+ .request_id = request_id ,
6929+ .handle_id = handle_id ,
6930+ .payload_len = payload_bin .size ,
6931+ };
6932+
6933+ /* Write header and payload */
6934+ if (write (w -> cmd_pipe [1 ], & header , sizeof (header )) == sizeof (header )) {
6935+ write (w -> cmd_pipe [1 ], payload_bin .data , payload_bin .size );
6936+ /* Wait for response */
6937+ owngil_header_t resp ;
6938+ read (w -> result_pipe [0 ], & resp , sizeof (resp ));
6939+ }
6940+
6941+ enif_release_binary (& payload_bin );
6942+ pthread_mutex_unlock (& w -> dispatch_mutex );
6943+
6944+ return ATOM_OK ;
6945+ }
6946+
6947+ /**
6948+ * @brief NIF: Apply paths to OWN_GIL session
6949+ *
6950+ * Adds paths to the worker's sys.path.
6951+ * Args: WorkerId, HandleId, Paths (list of path binaries)
6952+ */
6953+ static ERL_NIF_TERM nif_owngil_apply_paths (ErlNifEnv * env , int argc ,
6954+ const ERL_NIF_TERM argv []) {
6955+ if (argc != 3 ) {
6956+ return enif_make_badarg (env );
6957+ }
6958+
6959+ if (!subinterp_thread_pool_is_ready ()) {
6960+ return ATOM_OK ; /* Silently succeed if pool not ready */
6961+ }
6962+
6963+ unsigned int worker_id ;
6964+ ErlNifUInt64 handle_id ;
6965+
6966+ if (!enif_get_uint (env , argv [0 ], & worker_id ) ||
6967+ !enif_get_uint64 (env , argv [1 ], & handle_id )) {
6968+ return enif_make_badarg (env );
6969+ }
6970+
6971+ if (worker_id >= (unsigned int )g_thread_pool .num_workers ) {
6972+ return ATOM_OK ; /* Invalid worker, silently succeed */
6973+ }
6974+
6975+ /* Serialize paths list to ETF */
6976+ ErlNifBinary payload_bin ;
6977+ if (!enif_term_to_binary (env , argv [2 ], & payload_bin )) {
6978+ return ATOM_OK ; /* Serialization failed, silently succeed */
6979+ }
6980+
6981+ subinterp_thread_worker_t * w = & g_thread_pool .workers [worker_id ];
6982+
6983+ pthread_mutex_lock (& w -> dispatch_mutex );
6984+
6985+ uint64_t request_id = atomic_fetch_add (& g_thread_pool .next_request_id , 1 );
6986+ owngil_header_t header = {
6987+ .magic = OWNGIL_MAGIC ,
6988+ .version = OWNGIL_PROTOCOL_VERSION ,
6989+ .msg_type = MSG_REQUEST ,
6990+ .req_type = REQ_APPLY_PATHS ,
6991+ .request_id = request_id ,
6992+ .handle_id = handle_id ,
6993+ .payload_len = payload_bin .size ,
6994+ };
6995+
6996+ /* Write header and payload */
6997+ if (write (w -> cmd_pipe [1 ], & header , sizeof (header )) == sizeof (header )) {
6998+ write (w -> cmd_pipe [1 ], payload_bin .data , payload_bin .size );
6999+ /* Wait for response */
7000+ owngil_header_t resp ;
7001+ read (w -> result_pipe [0 ], & resp , sizeof (resp ));
7002+ }
7003+
7004+ enif_release_binary (& payload_bin );
7005+ pthread_mutex_unlock (& w -> dispatch_mutex );
7006+
7007+ return ATOM_OK ;
7008+ }
7009+
68847010#else /* !HAVE_SUBINTERPRETERS */
68857011
68867012/* Stub implementations for Python < 3.12 */
@@ -6980,6 +7106,18 @@ static ERL_NIF_TERM nif_owngil_destroy_session(ErlNifEnv *env, int argc,
69807106 return ATOM_OK ;
69817107}
69827108
7109+ static ERL_NIF_TERM nif_owngil_apply_imports (ErlNifEnv * env , int argc ,
7110+ const ERL_NIF_TERM argv []) {
7111+ (void )argc ; (void )argv ;
7112+ return ATOM_OK ;
7113+ }
7114+
7115+ static ERL_NIF_TERM nif_owngil_apply_paths (ErlNifEnv * env , int argc ,
7116+ const ERL_NIF_TERM argv []) {
7117+ (void )argc ; (void )argv ;
7118+ return ATOM_OK ;
7119+ }
7120+
69837121#endif /* HAVE_SUBINTERPRETERS */
69847122
69857123/* ============================================================================
@@ -7239,6 +7377,8 @@ static ErlNifFunc nif_funcs[] = {
72397377 {"owngil_create_session" , 1 , nif_owngil_create_session , 0 },
72407378 {"owngil_submit_task" , 7 , nif_owngil_submit_task , 0 },
72417379 {"owngil_destroy_session" , 2 , nif_owngil_destroy_session , 0 },
7380+ {"owngil_apply_imports" , 3 , nif_owngil_apply_imports , 0 },
7381+ {"owngil_apply_paths" , 3 , nif_owngil_apply_paths , 0 },
72427382
72437383 /* Execution mode info */
72447384 {"execution_mode" , 0 , nif_execution_mode , 0 },
0 commit comments