1 /*
2  * libZRTP SDK library, implements the ZRTP secure VoIP protocol.
3  * Copyright (c) 2006-2009 Philip R. Zimmermann.  All rights reserved.
4  * Contact: http://philzimmermann.com
5  * For licensing and other legal details, see the file zrtp_legal.c.
6  *
7  * Viktor Krykun <v.krikun at zfoneproject.com>
8  */
9 
10 #include "zrtp.h"
11 #include "queue.h"
12 
13 struct zrtp_queue {
14 	zrtp_sem_t*			size_sem;
15 	zrtp_sem_t*			main_sem;
16 	zrtp_mutex_t*		mutex;
17 	mlist_t				head;
18 	uint32_t			size;
19 };
20 
21 
zrtp_test_queue_create(zrtp_queue_t ** queue)22 zrtp_status_t zrtp_test_queue_create(zrtp_queue_t** queue) {
23 
24 	zrtp_status_t s = zrtp_status_fail;
25 	zrtp_queue_t* new_queue = (zrtp_queue_t*) zrtp_sys_alloc(sizeof(zrtp_queue_t));
26 	if (! new_queue) {
27 		return zrtp_status_fail;
28 	}
29 	zrtp_memset(new_queue, 0, sizeof(zrtp_queue_t));
30 
31 	do {
32 		s = zrtp_sem_init(&new_queue->size_sem, ZRTP_QUEUE_SIZE, ZRTP_QUEUE_SIZE);
33 		if (zrtp_status_ok != s) {
34 			break;
35 		}
36 		s = zrtp_sem_init(&new_queue->main_sem, 0, ZRTP_QUEUE_SIZE);
37 		if (zrtp_status_ok != s) {
38 			break;
39 		}
40 
41 		s = zrtp_mutex_init(&new_queue->mutex);
42 		if (zrtp_status_ok != s) {
43 			break;
44 		}
45 
46 		init_mlist(&new_queue->head);
47 		new_queue->size = 0;
48 
49 		s = zrtp_status_ok;
50 	} while (0);
51 
52 	if (zrtp_status_ok != s) {
53 		if (new_queue->size_sem) {
54 			zrtp_sem_destroy(new_queue->size_sem);
55 		}
56 		if (new_queue->main_sem) {
57 			zrtp_sem_destroy(new_queue->main_sem);
58 		}
59 		if (new_queue->mutex) {
60 			zrtp_mutex_destroy(new_queue->mutex);
61 		}
62 	}
63 
64 	*queue = new_queue;
65 
66     return s;
67 }
68 
zrtp_test_queue_destroy(zrtp_queue_t * queue)69 void zrtp_test_queue_destroy(zrtp_queue_t* queue) {
70 	if (queue->size_sem) {
71 		zrtp_sem_destroy(queue->size_sem);
72 	}
73 	if (queue->main_sem) {
74 		zrtp_sem_destroy(queue->main_sem);
75 	}
76 	if (queue->mutex) {
77 		zrtp_mutex_destroy(queue->mutex);
78 	}
79 }
80 
81 
zrtp_test_queue_push(zrtp_queue_t * queue,zrtp_queue_elem_t * elem)82 void zrtp_test_queue_push(zrtp_queue_t* queue, zrtp_queue_elem_t* elem) {
83 	zrtp_sem_wait(queue->size_sem);
84 
85 	zrtp_mutex_lock(queue->mutex);
86 	mlist_add_tail(&queue->head, &elem->_mlist);
87 	queue->size++;
88 	zrtp_mutex_unlock(queue->mutex);
89 
90 	zrtp_sem_post(queue->main_sem);
91 }
92 
zrtp_test_queue_pop(zrtp_queue_t * queue)93 zrtp_queue_elem_t* zrtp_test_queue_pop(zrtp_queue_t* queue) {
94 	zrtp_queue_elem_t* res = NULL;
95 	zrtp_sem_wait(queue->main_sem);
96 
97 	zrtp_mutex_lock(queue->mutex);
98 	if (queue->size) {
99 		zrtp_queue_elem_t* elem_cover = mlist_get_struct(zrtp_queue_elem_t, _mlist, queue->head.next);
100 		res = elem_cover;
101 		mlist_del(queue->head.next);
102 
103 		queue->size--;
104 		zrtp_sem_post(queue->size_sem);
105 	} else {
106 		zrtp_sem_post(queue->main_sem);
107 	}
108 	zrtp_mutex_unlock(queue->mutex);
109 
110 	return res;
111 }
112