source: CIVL/examples/compare/queue/twoLock.cvl

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 2.5 KB
Line 
1/* two_lock_queue.cvl: a "Two-Lock Concurrent
2 * Queue Algorithm", from Michael and Scott,
3 * https://www.cs.rochester.edu/research/synchronization/pseudocode/queues.html.
4 * Originally from "Simple, Fast, and
5 * Practical Non-Blocking and Blocking
6 * Concurrent Queue Algorithms", PODC96.
7 */
8#include <civlc.cvh>
9#include <stdbool.h>
10#include <stdlib.h>
11#include <assert.h>
12typedef int lock_t;
13#define FREE 0
14#define lock(l) $when (l==0) l=1;
15#define unlock(l) l=0;
16
17typedef struct node_t {
18 int value;
19 struct node_t *next;
20} node_t;
21
22typedef struct queue_t {
23 node_t *Head;
24 node_t *Tail;
25 lock_t H_lock;
26 lock_t T_lock;
27} queue_t;
28
29void initialize(queue_t *Q) {
30 node_t *node = (node_t*)malloc(sizeof(node_t));
31
32 node->next = NULL; // Make it the only node in the linked list
33 Q->Head = Q->Tail = node; // Both Head and Tail point to it
34 Q->H_lock = Q->T_lock = FREE; // Locks are initially free
35}
36
37void enqueue(queue_t *Q, int value) {
38 node_t *node = (node_t*)malloc(sizeof(node_t)); // in root scope
39
40 node->value = value; // Copy enqueued value into node
41 node->next = NULL; // Set next pointer of node to NULL
42 lock(Q->T_lock); // Acquire T_lock in order to access Tail
43 Q->Tail->next = node; // Link node at the end of the linked list
44 Q->Tail = node; // Swing Tail to node
45 unlock(Q->T_lock); // Release T_lock
46}
47
48_Bool dequeue(queue_t *Q, int *pvalue) {
49 node_t *node, *new_head;
50
51 lock(Q->H_lock); // Acquire H_lock in order to access Head
52 node = Q->Head; // Read Head
53 new_head = node->next; // Read next pointer
54 if (new_head == NULL) { // Is queue empty?
55 unlock(Q->H_lock); // Release H_lock before return
56 return false; // Queue was empty
57 }
58 *pvalue = new_head->value; // Queue not empty. Read value before release
59 Q->Head = new_head; // Swing Head to next node
60 unlock(Q->H_lock); // Release H_lock
61 free(node); // Free node
62 return true; // Queue was not empty, dequeue succeeded
63}
64
65#define N 2
66#define T 2
67$output int RESULT[T][N];
68int A[N];
69queue_t queue;
70
71void thread(int tid){
72 for(int i=0; i<N; i++)
73 enqueue(&queue, A[i]+tid*N);
74 for(int i=0; i<N; i++)
75 dequeue(&queue, &(RESULT[tid][i]));
76}
77
78int main(){
79 for(int i=0; i<N; i++)
80 A[i] = i+1;
81 for(int i=0; i<T; i++)
82 for(int j=0; j<N; j++)
83 RESULT[i][j] = 0;
84 initialize(&queue);
85 $parfor(int i: 0 .. T-1)
86 thread(i);
87 free(queue.Head);
88}
Note: See TracBrowser for help on using the repository browser.