@@ -5,11 +5,14 @@ use super::{
5
5
} ,
6
6
UNMANAGED_THREAD_START ,
7
7
} ;
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 ,
13
16
} ;
14
17
fn handle_to_obj ( asm : & mut Assembly , _: & mut MissingMethodPatcher ) {
15
18
let name = asm. alloc_string ( "handle_to_obj" ) ;
@@ -151,6 +154,20 @@ fn insert_pthread_attr_destroy(asm: &mut Assembly, patcher: &mut MissingMethodPa
151
154
} ;
152
155
patcher. insert ( name, Box :: new ( generator) ) ;
153
156
}
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
+ }
154
171
fn insert_pthread_join ( asm : & mut Assembly , patcher : & mut MissingMethodPatcher ) {
155
172
let fn_name = asm. alloc_string ( "pthread_join" ) ;
156
173
let generator = move |_, asm : & mut Assembly | {
@@ -198,7 +215,7 @@ fn insert_pthread_join(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) {
198
215
let thread_id =
199
216
asm. alloc_node ( CILNode :: Call ( Box :: new ( ( thread_id, [ joined_thread] . into ( ) ) ) ) ) ;
200
217
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) ;
202
219
let thread_results = asm. alloc_sfld ( StaticFieldDesc :: new (
203
220
* main_module,
204
221
thread_results,
@@ -360,9 +377,43 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
360
377
insert_pthread_attr_setstacksize ( asm, patcher) ;
361
378
insert_pthread_create ( asm, patcher) ;
362
379
insert_pthread_join ( asm, patcher) ;
380
+ insert_pthread_detach ( asm, patcher) ;
363
381
insert_pthread_self ( asm, patcher) ;
364
382
insert_pthread_attr_destroy ( asm, patcher) ;
365
383
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) ;
366
417
handle_to_obj ( asm, patcher) ;
367
418
368
419
let uts = asm. alloc_string ( UNMANAGED_THREAD_START ) ;
@@ -379,7 +430,7 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
379
430
Some ( object) ,
380
431
vec ! [ ( start_fn_tpe, start_fn, None ) , ( void_ptr, data, None ) ] ,
381
432
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.
383
434
Access :: Extern ,
384
435
None ,
385
436
) ) ;
@@ -455,7 +506,7 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
455
506
// Thread result static
456
507
let main_module = asm. main_module ( ) ;
457
508
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) ;
459
510
asm. class_mut ( main_module) . static_fields_mut ( ) . push ( (
460
511
Type :: ClassRef ( dict) ,
461
512
thread_results,
@@ -513,3 +564,145 @@ pub fn instert_threading(asm: &mut Assembly, patcher: &mut MissingMethodPatcher)
513
564
asm. alloc_class_ref( ClassRef :: new( uts, None , false , [ ] . into( ) ) )
514
565
) ;
515
566
}
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