@@ -293,10 +293,21 @@ inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
293
293
extern __CPROVER_bool __CPROVER_threads_exited [];
294
294
extern __CPROVER_thread_local unsigned long __CPROVER_thread_id ;
295
295
296
+ extern __CPROVER_thread_local const void * __CPROVER_thread_keys [];
297
+ extern __CPROVER_thread_local void (* __CPROVER_thread_key_dtors [])(void * );
298
+ extern __CPROVER_thread_local unsigned long __CPROVER_next_thread_key ;
299
+
296
300
inline void pthread_exit (void * value_ptr )
297
301
{
298
302
__CPROVER_HIDE :;
299
303
if (value_ptr != 0 ) (void )* (char * )value_ptr ;
304
+ for (unsigned long i = 0 ; i < __CPROVER_next_thread_key ; ++ i )
305
+ {
306
+ const void * key = __CPROVER_thread_keys [i ];
307
+ __CPROVER_thread_keys [i ] = 0 ;
308
+ if (__CPROVER_thread_key_dtors [i ] && key )
309
+ __CPROVER_thread_key_dtors [i ](key );
310
+ }
300
311
__CPROVER_threads_exited [__CPROVER_thread_id ]= 1 ;
301
312
__CPROVER_assume (0 );
302
313
}
@@ -524,6 +535,47 @@ extern __CPROVER_bool __CPROVER_threads_exited[];
524
535
extern __CPROVER_thread_local unsigned long __CPROVER_thread_id ;
525
536
extern unsigned long __CPROVER_next_thread_id ;
526
537
538
+ extern __CPROVER_thread_local const void * __CPROVER_thread_keys [];
539
+ extern __CPROVER_thread_local void (* __CPROVER_thread_key_dtors [])(void * );
540
+ extern __CPROVER_thread_local unsigned long __CPROVER_next_thread_key ;
541
+
542
+ inline void __spawned_thread (
543
+ unsigned long this_thread_id ,
544
+ void (* * thread_key_dtors )(void * ),
545
+ unsigned long next_thread_key ,
546
+ void * (* start_routine )(void * ),
547
+ void * arg )
548
+ {
549
+ __CPROVER_HIDE :;
550
+ __CPROVER_thread_id = this_thread_id ;
551
+ __CPROVER_next_thread_key = next_thread_key ;
552
+ for (unsigned long i = 0 ; i < __CPROVER_next_thread_key ; ++ i )
553
+ __CPROVER_thread_key_dtors [i ] = thread_key_dtors [i ];
554
+ #ifdef __CPROVER_CUSTOM_BITVECTOR_ANALYSIS
555
+ // Clear all locked mutexes; locking must happen in same thread.
556
+ __CPROVER_clear_must (0 , "mutex-locked" );
557
+ __CPROVER_clear_may (0 , "mutex-locked" );
558
+ #endif
559
+ start_routine (arg );
560
+ __CPROVER_fence (
561
+ "WWfence" ,
562
+ "RRfence" ,
563
+ "RWfence" ,
564
+ "WRfence" ,
565
+ "WWcumul" ,
566
+ "RRcumul" ,
567
+ "RWcumul" ,
568
+ "WRcumul" );
569
+ for (unsigned long i = 0 ; i < __CPROVER_next_thread_key ; ++ i )
570
+ {
571
+ const void * key = __CPROVER_thread_keys [i ];
572
+ __CPROVER_thread_keys [i ] = 0 ;
573
+ if (__CPROVER_thread_key_dtors [i ] && key )
574
+ __CPROVER_thread_key_dtors [i ](key );
575
+ }
576
+ __CPROVER_threads_exited [this_thread_id ] = 1 ;
577
+ }
578
+
527
579
inline int pthread_create (
528
580
pthread_t * thread , // must not be null
529
581
const pthread_attr_t * attr , // may be null
@@ -545,19 +597,14 @@ inline int pthread_create(
545
597
546
598
if (attr ) (void )* attr ;
547
599
600
+ unsigned long next_thread_key = __CPROVER_next_thread_key ;
601
+ void (* * thread_key_dtors )(void * ) = __CPROVER_thread_key_dtors ;
602
+
548
603
__CPROVER_ASYNC_1 :
549
- __CPROVER_thread_id = this_thread_id ,
550
- #ifdef __CPROVER_CUSTOM_BITVECTOR_ANALYSIS
551
- // Clear all locked mutexes; locking must happen in same thread.
552
- __CPROVER_clear_must (0 , "mutex-locked" ),
553
- __CPROVER_clear_may (0 , "mutex-locked" ),
554
- #endif
555
- start_routine (arg ),
556
- __CPROVER_fence ("WWfence" , "RRfence" , "RWfence" , "WRfence" ,
557
- "WWcumul" , "RRcumul" , "RWcumul" , "WRcumul" ),
558
- __CPROVER_threads_exited [this_thread_id ]= 1 ;
604
+ __spawned_thread (
605
+ this_thread_id , thread_key_dtors , next_thread_key , start_routine , arg );
559
606
560
- return 0 ;
607
+ return 0 ;
561
608
}
562
609
563
610
/* FUNCTION: pthread_cond_init */
@@ -832,3 +879,70 @@ inline int pthread_barrier_wait(pthread_barrier_t *barrier)
832
879
return result ;
833
880
}
834
881
#endif
882
+
883
+ /* FUNCTION: pthread_key_create */
884
+
885
+ #ifndef __CPROVER_PTHREAD_H_INCLUDED
886
+ #include <pthread.h>
887
+ #define __CPROVER_PTHREAD_H_INCLUDED
888
+ #endif
889
+
890
+ extern __CPROVER_thread_local const void * __CPROVER_thread_keys [];
891
+ extern __CPROVER_thread_local void (* __CPROVER_thread_key_dtors [])(void * );
892
+ extern __CPROVER_thread_local unsigned long __CPROVER_next_thread_key ;
893
+
894
+ inline int pthread_key_create (pthread_key_t * key , void (* destructor )(void * ))
895
+ {
896
+ __CPROVER_HIDE :;
897
+ __CPROVER_thread_keys [__CPROVER_next_thread_key ] = 0 ;
898
+ __CPROVER_thread_key_dtors [__CPROVER_next_thread_key ] = destructor ;
899
+ * key = __CPROVER_next_thread_key ++ ;
900
+ return 0 ;
901
+ }
902
+
903
+ /* FUNCTION: pthread_key_delete */
904
+
905
+ #ifndef __CPROVER_PTHREAD_H_INCLUDED
906
+ #include <pthread.h>
907
+ #define __CPROVER_PTHREAD_H_INCLUDED
908
+ #endif
909
+
910
+ extern __CPROVER_thread_local const void * __CPROVER_thread_keys [];
911
+
912
+ inline int pthread_key_delete (pthread_key_t key )
913
+ {
914
+ __CPROVER_HIDE :;
915
+ __CPROVER_thread_keys [key ] = 0 ;
916
+ return 0 ;
917
+ }
918
+
919
+ /* FUNCTION: pthread_getspecific */
920
+
921
+ #ifndef __CPROVER_PTHREAD_H_INCLUDED
922
+ #include <pthread.h>
923
+ #define __CPROVER_PTHREAD_H_INCLUDED
924
+ #endif
925
+
926
+ extern __CPROVER_thread_local const void * __CPROVER_thread_keys [];
927
+
928
+ inline void * pthread_getspecific (pthread_key_t key )
929
+ {
930
+ __CPROVER_HIDE :;
931
+ return (void * )__CPROVER_thread_keys [key ];
932
+ }
933
+
934
+ /* FUNCTION: pthread_setspecific */
935
+
936
+ #ifndef __CPROVER_PTHREAD_H_INCLUDED
937
+ #include <pthread.h>
938
+ #define __CPROVER_PTHREAD_H_INCLUDED
939
+ #endif
940
+
941
+ extern __CPROVER_thread_local const void * __CPROVER_thread_keys [];
942
+
943
+ inline int pthread_setspecific (pthread_key_t key , const void * value )
944
+ {
945
+ __CPROVER_HIDE :;
946
+ __CPROVER_thread_keys [key ] = value ;
947
+ return 0 ;
948
+ }
0 commit comments