File: main.c

package info (click to toggle)
cbmc 6.6.0-4
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 153,852 kB
  • sloc: cpp: 386,459; ansic: 114,466; java: 28,405; python: 6,003; yacc: 4,552; makefile: 4,041; lex: 2,487; xml: 2,388; sh: 2,050; perl: 557; pascal: 184; javascript: 163; ada: 36
file content (98 lines) | stat: -rw-r--r-- 2,066 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include <pthread.h>
#include <assert.h>

// ========= Chord library =========

// This struct is not thread-safe itself!
//
// A chord is like a chain of threads `f, g, ...` where `f`
// must terminate before `g` can start to run, and so forth.
struct chord_t
{
  // last thread in chain
  pthread_t thread;
};

// Public function pointer
typedef void *(*start_routine)(void *);

// Internal
struct chord_args_t
{
  // last thread in chain
  pthread_t thread;

  // function pointer for new thread
  start_routine f;

  // argument to f
  void *f_arg;
};

// Internal start routine for a thread in a chord
static void* chord_start_routine(void *ptr)
{
  struct chord_args_t *args = (struct chord_args_t *) ptr;

  // ignore errors
  pthread_join(args->thread, NULL);
  return args->f(args->f_arg);
}

// This function is not thread-safe itself!
//
// Create a new thread for `f` where `f(arg)` starts to run as
// soon as the currently running `self->thread` has terminated.
//
// \post: self->thread is the newly created thread for `f`
int chord_run(struct chord_t *self, start_routine f, void *arg)
{
  struct chord_args_t args;
  args.thread = self->thread;
  args.f = f;
  args.f_arg = arg;

  return pthread_create(&(self->thread), NULL, chord_start_routine, (void *) &args);
}

// ========= Symbolic test =========

char test_global;

void* test_write_a( void *arg)
{
  test_global = 'A';
  return NULL;
}

void* test_write_b(void *arg)
{
  test_global = 'B';
  return NULL;
}

int main(void)
{
#ifdef _ENABLE_CHORD_
  struct chord_t chord;
  chord_run(&chord, test_write_a, NULL);
  chord_run(&chord, test_write_b, NULL);
#else
  pthread_t a_thread, b_thread;
  pthread_create(&a_thread, NULL, test_write_a, NULL);
  pthread_create(&b_thread, NULL, test_write_b, NULL);
#endif

  char x = test_global;
  char y = test_global;

  // Verification condition:
  //
  //  If global variable equals 'B', then it cannot change.
  //
  // It is expected that this implication
  // fails if _ENABLE_CHORD_ is undefined.
  assert(x != 'B' || y == 'B');

  return 0;
}