Skip to content

Commit d12d57a

Browse files
committed
Add posix semaphore examples
1 parent 8057098 commit d12d57a

File tree

7 files changed

+235
-0
lines changed

7 files changed

+235
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#include <assert.h>
2+
#include <pthread.h>
3+
#include <semaphore.h>
4+
#include <stdbool.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
8+
void *worker(void *arguments);
9+
10+
#include "util.c"
11+
12+
struct blocking_queuet
13+
{
14+
size_t size;
15+
int *elements;
16+
size_t begin;
17+
size_t end;
18+
sem_t free_space;
19+
sem_t data_waiting;
20+
};
21+
22+
struct blocking_queuet initialise_blocking_queue(const size_t size)
23+
{
24+
printf("init queue begin\n");
25+
struct blocking_queuet queue;
26+
queue.size = size;
27+
queue.elements = calloc(size, sizeof(int));
28+
queue.begin = 0;
29+
queue.end = 0;
30+
queue.free_space = create_semaphore(size);
31+
queue.data_waiting = create_semaphore(0);
32+
printf("init queue end\n");
33+
return queue;
34+
}
35+
36+
void free_blocking_queue(struct blocking_queuet *queue)
37+
{
38+
free(queue->elements);
39+
queue->elements = NULL;
40+
destroy_semaphore(&queue->free_space);
41+
destroy_semaphore(&queue->data_waiting);
42+
}
43+
44+
void enqueue(struct blocking_queuet *queue, const int data)
45+
{
46+
printf(
47+
"enqueue begin:%lu end:%lu data:%d \n", queue->begin, queue->end, data);
48+
const int free_wait_error = sem_wait(&queue->free_space);
49+
assert(free_wait_error == false);
50+
queue->elements[queue->end] = data;
51+
if(++queue->end == queue->size)
52+
{
53+
queue->end = 0;
54+
}
55+
const int post_error = sem_post(&queue->data_waiting);
56+
assert(post_error == false);
57+
printf("enqueue done\n");
58+
}
59+
60+
int dequeue(struct blocking_queuet *queue)
61+
{
62+
printf("dequeue begin:%lu end:%lu\n", queue->begin, queue->end);
63+
const int data_wait_error = sem_wait(&queue->data_waiting);
64+
assert(data_wait_error == false);
65+
int result = queue->elements[queue->begin];
66+
if(++queue->begin == queue->size)
67+
{
68+
queue->begin = 0;
69+
}
70+
const int free_error = sem_post(&queue->free_space);
71+
assert(free_error == false);
72+
printf("dequeue done. data:%d \n", result);
73+
return result;
74+
}
75+
76+
struct blocking_queuet input_queue;
77+
struct blocking_queuet output_queue;
78+
79+
void *worker(void *arguments)
80+
{
81+
int data;
82+
while(data = dequeue(&input_queue))
83+
{
84+
enqueue(&output_queue, data * data);
85+
}
86+
pthread_exit(NULL);
87+
}
88+
89+
int main(void)
90+
{
91+
input_queue = initialise_blocking_queue(3);
92+
output_queue = initialise_blocking_queue(10);
93+
const pthread_t worker_thread1 = start_worker_thread();
94+
printf("worker_started\n");
95+
enqueue(&input_queue, 1);
96+
enqueue(&input_queue, 2);
97+
enqueue(&input_queue, 3);
98+
enqueue(&input_queue, 4);
99+
enqueue(&input_queue, 5);
100+
enqueue(&input_queue, 6);
101+
enqueue(&input_queue, 7);
102+
enqueue(&input_queue, 8);
103+
enqueue(&input_queue, 9);
104+
enqueue(&input_queue, 0);
105+
join_thread(worker_thread1);
106+
free_blocking_queue(&input_queue);
107+
assert(dequeue(&output_queue) == 1);
108+
assert(dequeue(&output_queue) == 4);
109+
assert(dequeue(&output_queue) == 9);
110+
assert(dequeue(&output_queue) == 16);
111+
assert(dequeue(&output_queue) == 25);
112+
assert(dequeue(&output_queue) == 36);
113+
assert(dequeue(&output_queue) == 49);
114+
assert(dequeue(&output_queue) == 64);
115+
assert(dequeue(&output_queue) == 81);
116+
free_blocking_queue(&output_queue);
117+
return EXIT_SUCCESS;
118+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FUTURE
2+
blocking_queue.c
3+
^EXIT=0$
4+
^SIGNAL=0$
5+
^VERIFICATION SUCCESSFUL$
6+
--
7+
^warning: ignoring
8+
pointer handling for concurrency is unsound
9+
--
10+
Test using an example simplistic implementation of a blocking queue.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <assert.h>
2+
#include <pthread.h>
3+
#include <semaphore.h>
4+
#include <stdbool.h>
5+
#include <stdlib.h>
6+
7+
sem_t global_semaphore;
8+
int global_value;
9+
10+
void *worker(void *arguments)
11+
{
12+
const int wait_error = sem_wait(&global_semaphore);
13+
assert(wait_error == false);
14+
assert(global_value == 42);
15+
pthread_exit(NULL);
16+
}
17+
18+
#include "util.c"
19+
20+
int main(void)
21+
{
22+
global_semaphore = create_semaphore(0);
23+
global_value = 0;
24+
25+
const pthread_t worker_thread1 = start_worker_thread();
26+
global_value = 42;
27+
const int post_error = sem_post(&global_semaphore);
28+
assert(post_error == false);
29+
join_thread(worker_thread1);
30+
31+
destroy_semaphore(&global_semaphore);
32+
return EXIT_SUCCESS;
33+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FUTURE
2+
blocking_wait.c
3+
^EXIT=0$
4+
^SIGNAL=0$
5+
^VERIFICATION SUCCESSFUL$
6+
--
7+
^warning: ignoring
8+
pointer handling for concurrency is unsound
9+
--
10+
Test that sem_wait will block when the value of a semaphore is 0, until it is
11+
increased via sem_post.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <assert.h>
2+
#include <pthread.h>
3+
#include <semaphore.h>
4+
#include <stdbool.h>
5+
#include <stdlib.h>
6+
7+
sem_t global_semaphore;
8+
9+
void *worker(void *arguments)
10+
{
11+
}
12+
13+
#include "util.c"
14+
15+
int main(void)
16+
{
17+
global_semaphore = create_semaphore(0);
18+
destroy_semaphore(&global_semaphore);
19+
return EXIT_SUCCESS;
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
create_destroy.c
3+
^EXIT=0$
4+
^SIGNAL=0$
5+
^VERIFICATION SUCCESSFUL$
6+
--
7+
^warning: ignoring
8+
pointer handling for concurrency is unsound
9+
--
10+
Sanity check that cbmc can deal with creation and destruction of semaphores.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
pthread_t start_worker_thread(void)
3+
{
4+
pthread_t worker_thread;
5+
const pthread_attr_t *const attributes = NULL;
6+
void *const worker_argument = NULL;
7+
const int create_status =
8+
pthread_create(&worker_thread, attributes, &worker, worker_argument);
9+
assert(create_status == 0);
10+
return worker_thread;
11+
}
12+
13+
void join_thread(const pthread_t thread)
14+
{
15+
const int join_status = pthread_join(thread, NULL);
16+
assert(join_status == 0);
17+
}
18+
19+
sem_t create_semaphore(int initial_value)
20+
{
21+
const int shared_between_processes = false;
22+
sem_t semaphore;
23+
const int init_error =
24+
sem_init(&semaphore, shared_between_processes, initial_value);
25+
assert(init_error == false);
26+
return semaphore;
27+
}
28+
29+
void destroy_semaphore(sem_t *const semaphore)
30+
{
31+
int destroy_error = sem_destroy(semaphore);
32+
assert(destroy_error == false);
33+
}

0 commit comments

Comments
 (0)