@@ -5,11 +5,14 @@ use super::{
55 } ,
66 UNMANAGED_THREAD_START ,
77} ;
8- use crate :: v2:: {
9- cilnode:: { ExtendKind , PtrCastRes } ,
10- cilroot:: BranchCond ,
11- tpe:: GenericKind ,
12- BinOp , StaticFieldDesc ,
8+ use crate :: {
9+ v2:: {
10+ cilnode:: { ExtendKind , PtrCastRes } ,
11+ cilroot:: BranchCond ,
12+ tpe:: GenericKind ,
13+ BinOp , StaticFieldDesc ,
14+ } ,
15+ ClassRefIdx ,
1316} ;
1417fn handle_to_obj ( asm : & mut Assembly , _: & mut MissingMethodPatcher ) {
1518 let name = asm. alloc_string ( "handle_to_obj" ) ;
@@ -151,6 +154,20 @@ fn insert_pthread_attr_destroy(asm: &mut Assembly, patcher: &mut MissingMethodPa
151154 } ;
152155 patcher. insert ( name, Box :: new ( generator) ) ;
153156}
157+ // TODO: impl detach
158+ fn insert_pthread_detach ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
159+ let fn_name = asm. alloc_string ( "pthread_detach" ) ;
160+ let generator = move |_, asm : & mut Assembly | {
161+ // Return 0 to signal success.
162+ let const_0 = asm. alloc_node ( Const :: I32 ( 0 ) ) ;
163+ let ret_0 = asm. alloc_root ( CILRoot :: Ret ( const_0) ) ;
164+ MethodImpl :: MethodBody {
165+ blocks : vec ! [ BasicBlock :: new( vec![ ret_0] , 0 , None ) ] ,
166+ locals : vec ! [ ] ,
167+ }
168+ } ;
169+ patcher. insert ( fn_name, Box :: new ( generator) ) ;
170+ }
154171fn insert_pthread_join ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
155172 let fn_name = asm. alloc_string ( "pthread_join" ) ;
156173 let generator = move |_, asm : & mut Assembly | {
@@ -198,7 +215,7 @@ fn insert_pthread_join(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
198215 let thread_id =
199216 asm. alloc_node ( CILNode :: Call ( Box :: new ( ( thread_id, [ joined_thread] . into ( ) ) ) ) ) ;
200217 let thread_results = asm. alloc_string ( "thread_results" ) ;
201- let dict = ClassRef :: dictionary ( Type :: Int ( Int :: I32 ) , Type :: Int ( Int :: ISize ) , asm) ;
218+ let dict = ClassRef :: concurent_dictionary ( Type :: Int ( Int :: I32 ) , Type :: Int ( Int :: ISize ) , asm) ;
202219 let thread_results = asm. alloc_sfld ( StaticFieldDesc :: new (
203220 * main_module,
204221 thread_results,
@@ -360,9 +377,43 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
360377 insert_pthread_attr_setstacksize ( asm, patcher) ;
361378 insert_pthread_create ( asm, patcher) ;
362379 insert_pthread_join ( asm, patcher) ;
380+ insert_pthread_detach ( asm, patcher) ;
363381 insert_pthread_self ( asm, patcher) ;
364382 insert_pthread_attr_destroy ( asm, patcher) ;
365383 insert_pthread_setname_np ( asm, patcher) ;
384+ insert_pthread_key_delete ( asm, patcher) ;
385+ let main_mod = asm. main_module ( ) ;
386+ asm. add_static ( Type :: Int ( PTHREAD_KEY_T ) , "last_val" , false , main_mod) ;
387+ let thread_key_dict = thread_key_dict ( asm) ;
388+ asm. add_static (
389+ Type :: ClassRef ( thread_key_dict) ,
390+ "pthread_keys" ,
391+ true ,
392+ main_mod,
393+ ) ;
394+ let pthread_keys = asm. alloc_string ( "pthread_keys" ) ;
395+ let pthread_keys_static = asm. alloc_sfld ( StaticFieldDesc :: new (
396+ * main_mod,
397+ pthread_keys,
398+ Type :: ClassRef ( thread_key_dict) ,
399+ ) ) ;
400+ let thread_key_dict_ctor = asm[ thread_key_dict] . clone ( ) . ctor ( & [ ] , asm) ;
401+ let ctor = asm. alloc_node ( CILNode :: Call ( Box :: new ( ( thread_key_dict_ctor, [ ] . into ( ) ) ) ) ) ;
402+ let init_dict = asm. alloc_root ( CILRoot :: SetStaticField {
403+ field : pthread_keys_static,
404+ val : ctor,
405+ } ) ;
406+ let last_val = asm. alloc_string ( "last_val" ) ;
407+ let last_val_static = StaticFieldDesc :: new ( * main_mod, last_val, Type :: Int ( PTHREAD_KEY_T ) ) ;
408+ let last_val_static = asm. alloc_sfld ( last_val_static) ;
409+ let val = asm. alloc_node ( Const :: I32 ( 1 ) ) ;
410+ let init_val = asm. alloc_root ( CILRoot :: SetStaticField {
411+ field : last_val_static,
412+ val,
413+ } ) ;
414+ asm. add_tcctor ( & [ init_val, init_dict] ) ;
415+ insert_pthread_key_create ( asm, patcher) ;
416+ insert_pthread_setspecific ( asm, patcher) ;
366417 handle_to_obj ( asm, patcher) ;
367418
368419 let uts = asm. alloc_string ( UNMANAGED_THREAD_START ) ;
@@ -379,7 +430,7 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
379430 Some ( object) ,
380431 vec ! [ ( start_fn_tpe, start_fn, None ) , ( void_ptr, data, None ) ] ,
381432 vec ! [ ] ,
382- // TODO: fix the bug which causes this to be leaned up by dead code elimination when access is set to Public.
433+ // TODO: fix the bug which causes this to be cleaned up by dead code elimination when access is set to Public.
383434 Access :: Extern ,
384435 None ,
385436 ) ) ;
@@ -455,7 +506,7 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
455506 // Thread result static
456507 let main_module = asm. main_module ( ) ;
457508 let thread_results = asm. alloc_string ( "thread_results" ) ;
458- let dict = ClassRef :: dictionary ( Type :: Int ( Int :: I32 ) , Type :: Int ( Int :: ISize ) , asm) ;
509+ let dict = ClassRef :: concurent_dictionary ( Type :: Int ( Int :: I32 ) , Type :: Int ( Int :: ISize ) , asm) ;
459510 asm. class_mut ( main_module) . static_fields_mut ( ) . push ( (
460511 Type :: ClassRef ( dict) ,
461512 thread_results,
@@ -513,3 +564,145 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
513564 asm. alloc_class_ref( ClassRef :: new( uts, None , false , [ ] . into( ) ) )
514565 ) ;
515566}
567+ const PTHREAD_KEY_T : Int = Int :: I32 ;
568+ fn thread_key_dict ( asm : & mut Assembly ) -> ClassRefIdx {
569+ ClassRef :: dictionary ( Type :: Int ( PTHREAD_KEY_T ) , Type :: Int ( Int :: ISize ) , asm)
570+ }
571+ fn insert_pthread_setspecific ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
572+ let name = asm. alloc_string ( "pthread_setspecific" ) ;
573+ let generator = move |_, asm : & mut Assembly | {
574+ let main_mod = * asm. main_module ( ) ;
575+ let const_0 = asm. alloc_node ( Const :: I32 ( 0 ) ) ;
576+ let ret = asm. alloc_root ( CILRoot :: Ret ( const_0) ) ;
577+
578+ // Insert a new key into the dict.
579+ let thread_key_dict = thread_key_dict ( asm) ;
580+ let pthread_keys = asm. alloc_string ( "pthread_keys" ) ;
581+ let pthread_keys_static = asm. alloc_sfld ( StaticFieldDesc :: new (
582+ main_mod,
583+ pthread_keys,
584+ Type :: ClassRef ( thread_key_dict) ,
585+ ) ) ;
586+ let pthread_keys = asm. alloc_node ( CILNode :: LdStaticField ( pthread_keys_static) ) ;
587+
588+ let set_item = asm. alloc_string ( "set_Item" ) ;
589+ let dict_add = asm[ thread_key_dict] . clone ( ) . virtual_mref (
590+ & [
591+ Type :: PlatformGeneric ( 0 , GenericKind :: TypeGeneric ) ,
592+ Type :: PlatformGeneric ( 1 , GenericKind :: TypeGeneric ) ,
593+ ] ,
594+ Type :: Void ,
595+ set_item,
596+ asm,
597+ ) ;
598+ let arg_0 = asm. alloc_node ( CILNode :: LdArg ( 0 ) ) ;
599+ let arg_1 = asm. alloc_node ( CILNode :: LdArg ( 1 ) ) ;
600+ let insert_key = asm. alloc_root ( CILRoot :: Call ( Box :: new ( (
601+ dict_add,
602+ [ pthread_keys, arg_0, arg_1] . into ( ) ,
603+ ) ) ) ) ;
604+ // Set the key_t to this key.
605+
606+ MethodImpl :: MethodBody {
607+ blocks : vec ! [ BasicBlock :: new( vec![ insert_key, ret] , 0 , None ) ] ,
608+ locals : vec ! [ ] ,
609+ }
610+ } ;
611+ patcher. insert ( name, Box :: new ( generator) ) ;
612+ }
613+ fn insert_pthread_key_create ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
614+ let name = asm. alloc_string ( "pthread_key_create" ) ;
615+ let generator = move |_, asm : & mut Assembly | {
616+ let main_mod = * asm. main_module ( ) ;
617+ let const_0 = asm. alloc_node ( Const :: I32 ( 0 ) ) ;
618+ let ret = asm. alloc_root ( CILRoot :: Ret ( const_0) ) ;
619+ let last_val = asm. alloc_string ( "last_val" ) ;
620+ let last_val_static = StaticFieldDesc :: new ( main_mod, last_val, Type :: Int ( PTHREAD_KEY_T ) ) ;
621+ let last_val_static = asm. alloc_sfld ( last_val_static) ;
622+ // Save the last counter value
623+ let last_value = asm. alloc_node ( CILNode :: LdStaticField ( last_val_static) ) ;
624+ let save_last_val = asm. alloc_root ( CILRoot :: StLoc ( 0 , last_value) ) ;
625+ // Increment the last counter value
626+ let one = asm. alloc_node ( Const :: I32 ( 0 ) ) ;
627+ let incremented = asm. alloc_node ( CILNode :: BinOp ( last_value, one, BinOp :: Add ) ) ;
628+ let increment_val = asm. alloc_root ( CILRoot :: StLoc ( 0 , incremented) ) ;
629+ // Insert a new key into the dict.
630+ let thread_key_dict = thread_key_dict ( asm) ;
631+ let pthread_keys = asm. alloc_string ( "pthread_keys" ) ;
632+ let pthread_keys_static = asm. alloc_sfld ( StaticFieldDesc :: new (
633+ main_mod,
634+ pthread_keys,
635+ Type :: ClassRef ( thread_key_dict) ,
636+ ) ) ;
637+ let pthread_keys = asm. alloc_node ( CILNode :: LdStaticField ( pthread_keys_static) ) ;
638+ let zero_isize = asm. alloc_node ( Const :: ISize ( 0 ) ) ;
639+ let loc_0 = asm. alloc_node ( CILNode :: LdLoc ( 0 ) ) ;
640+ let add_name = asm. alloc_string ( "set_Item" ) ;
641+ let dict_add = asm[ thread_key_dict] . clone ( ) . virtual_mref (
642+ & [
643+ Type :: PlatformGeneric ( 0 , GenericKind :: TypeGeneric ) ,
644+ Type :: PlatformGeneric ( 1 , GenericKind :: TypeGeneric ) ,
645+ ] ,
646+ Type :: Void ,
647+ add_name,
648+ asm,
649+ ) ;
650+ let insert_key = asm. alloc_root ( CILRoot :: Call ( Box :: new ( (
651+ dict_add,
652+ [ pthread_keys, zero_isize, loc_0] . into ( ) ,
653+ ) ) ) ) ;
654+ // Set the key_t to this key.
655+ let arg_0 = asm. alloc_node ( CILNode :: LdArg ( 0 ) ) ;
656+ let key_t = asm. alloc_type ( Type :: Int ( PTHREAD_KEY_T ) ) ;
657+ let arg_0 = asm. alloc_node ( CILNode :: PtrCast ( arg_0, Box :: new ( PtrCastRes :: Ptr ( key_t) ) ) ) ;
658+ let set_key = asm. alloc_root ( CILRoot :: StInd ( Box :: new ( (
659+ arg_0,
660+ loc_0,
661+ Type :: Int ( PTHREAD_KEY_T ) ,
662+ false ,
663+ ) ) ) ) ;
664+ MethodImpl :: MethodBody {
665+ blocks : vec ! [ BasicBlock :: new(
666+ vec![ save_last_val, increment_val, insert_key, set_key, ret] ,
667+ 0 ,
668+ None ,
669+ ) ] ,
670+ locals : vec ! [ ( None , key_t) ] ,
671+ }
672+ } ;
673+ patcher. insert ( name, Box :: new ( generator) ) ;
674+ }
675+ fn insert_pthread_key_delete ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
676+ let name = asm. alloc_string ( "pthread_key_delete" ) ;
677+ let generator = move |_, asm : & mut Assembly | {
678+ let main_mod = * asm. main_module ( ) ;
679+ let const_0 = asm. alloc_node ( Const :: I32 ( 0 ) ) ;
680+ let ret = asm. alloc_root ( CILRoot :: Ret ( const_0) ) ;
681+ let thread_key_dict = thread_key_dict ( asm) ;
682+ let pthread_keys = asm. alloc_string ( "pthread_keys" ) ;
683+ let pthread_keys_static = asm. alloc_sfld ( StaticFieldDesc :: new (
684+ main_mod,
685+ pthread_keys,
686+ Type :: ClassRef ( thread_key_dict) ,
687+ ) ) ;
688+ let pthread_keys = asm. alloc_node ( CILNode :: LdStaticField ( pthread_keys_static) ) ;
689+ let arg_0 = asm. alloc_node ( CILNode :: LdArg ( 0 ) ) ;
690+ let add_name = asm. alloc_string ( "Remove" ) ;
691+ let dict_rem = asm[ thread_key_dict] . clone ( ) . virtual_mref (
692+ & [ Type :: PlatformGeneric ( 0 , GenericKind :: TypeGeneric ) ] ,
693+ Type :: Bool ,
694+ add_name,
695+ asm,
696+ ) ;
697+ let remove_key = asm. alloc_node ( CILNode :: Call ( Box :: new ( (
698+ dict_rem,
699+ [ pthread_keys, arg_0] . into ( ) ,
700+ ) ) ) ) ;
701+ let remove_key = asm. alloc_root ( CILRoot :: Pop ( remove_key) ) ;
702+ MethodImpl :: MethodBody {
703+ blocks : vec ! [ BasicBlock :: new( vec![ remove_key, ret] , 0 , None ) ] ,
704+ locals : vec ! [ ] ,
705+ }
706+ } ;
707+ patcher. insert ( name, Box :: new ( generator) ) ;
708+ }
0 commit comments