Skip to content

Commit 71b0a07

Browse files
committed
C library: model pthread_key_create, pthread_{get,set}specific
This is used by pthread-divine/tls_basic_true-unreach-call in SV-COMP.
1 parent b02b2fd commit 71b0a07

File tree

5 files changed

+145
-15
lines changed

5 files changed

+145
-15
lines changed

regression/goto-analyzer/constant_propagation_01/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--constants --simplify out.gb
44
^EXIT=0$
55
^SIGNAL=0$
6-
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 5, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 12, function calls: 2$
6+
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$
7+
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 15, function calls: 2$
88
--
99
^warning: ignoring

regression/goto-analyzer/constant_propagation_02/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--constants --simplify out.gb
44
^EXIT=0$
55
^SIGNAL=0$
6-
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 6, function calls: 0$
7-
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 11, function calls: 2$
6+
^Simplified: assert: 1, assume: 0, goto: 1, assigns: 7, function calls: 0$
7+
^Unmodified: assert: 0, assume: 0, goto: 0, assigns: 14, function calls: 2$
88
--
99
^warning: ignoring

src/ansi-c/ansi_c_internal_additions.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ void ansi_c_internal_additions(std::string &code)
136136
CPROVER_PREFIX "bool " CPROVER_PREFIX "threads_exited["
137137
CPROVER_PREFIX "constant_infinity_uint];\n"
138138
"unsigned long " CPROVER_PREFIX "next_thread_id=0;\n"
139+
CPROVER_PREFIX "thread_local const void* " CPROVER_PREFIX "thread_keys["
140+
CPROVER_PREFIX "constant_infinity_uint];\n"
141+
CPROVER_PREFIX "thread_local void (*" CPROVER_PREFIX "thread_key_dtors["
142+
CPROVER_PREFIX "constant_infinity_uint])(void *);\n"
143+
CPROVER_PREFIX "thread_local unsigned long "
144+
CPROVER_PREFIX "next_thread_key = 0;\n"
139145
"extern unsigned char " CPROVER_PREFIX "memory["
140146
CPROVER_PREFIX "constant_infinity_uint];\n"
141147

src/ansi-c/library/pthread_lib.c

Lines changed: 125 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,21 @@ inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
293293
extern __CPROVER_bool __CPROVER_threads_exited[];
294294
extern __CPROVER_thread_local unsigned long __CPROVER_thread_id;
295295

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+
296300
inline void pthread_exit(void *value_ptr)
297301
{
298302
__CPROVER_HIDE:;
299303
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+
}
300311
__CPROVER_threads_exited[__CPROVER_thread_id]=1;
301312
__CPROVER_assume(0);
302313
}
@@ -524,6 +535,47 @@ extern __CPROVER_bool __CPROVER_threads_exited[];
524535
extern __CPROVER_thread_local unsigned long __CPROVER_thread_id;
525536
extern unsigned long __CPROVER_next_thread_id;
526537

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+
527579
inline int pthread_create(
528580
pthread_t *thread, // must not be null
529581
const pthread_attr_t *attr, // may be null
@@ -545,19 +597,14 @@ inline int pthread_create(
545597

546598
if(attr) (void)*attr;
547599

600+
unsigned long next_thread_key = __CPROVER_next_thread_key;
601+
void (**thread_key_dtors)(void *) = __CPROVER_thread_key_dtors;
602+
548603
__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);
559606

560-
return 0;
607+
return 0;
561608
}
562609

563610
/* FUNCTION: pthread_cond_init */
@@ -832,3 +879,70 @@ inline int pthread_barrier_wait(pthread_barrier_t *barrier)
832879
return result;
833880
}
834881
#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+
}

src/cpp/cpp_internal_additions.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ void cpp_internal_additions(std::ostream &out)
7272
<< CPROVER_PREFIX "threads_exited[__CPROVER::constant_infinity_uint];"
7373
<< '\n';
7474
out << "unsigned long " CPROVER_PREFIX "next_thread_id = 0;" << '\n';
75+
// TODO: thread_local is still broken
76+
out << "void* "
77+
<< CPROVER_PREFIX "thread_keys[__CPROVER::constant_infinity_uint];"
78+
<< '\n';
79+
// TODO: thread_local is still broken
80+
out << "void (*"
81+
<< CPROVER_PREFIX "thread_key_dtors[__CPROVER::constant_infinity_uint])"
82+
<< "(void *);" << '\n';
83+
// TODO: thread_local is still broken
84+
out << "unsigned long " CPROVER_PREFIX "next_thread_key = 0;" << '\n';
7585
out << "extern unsigned char "
7686
<< CPROVER_PREFIX "memory[__CPROVER::constant_infinity_uint];" << '\n';
7787

0 commit comments

Comments
 (0)