1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 #include <sys/types.h>
17 #include <sys/kmem.h>
18 #include <sys/ddi.h>
19 #include <sys/sunddi.h>
20 #include <sys/time.h>
21 #include <sys/sysmacros.h>
22 #include <sys/debug.h>
23
24 #include "krrp_queue.h"
25
26 void
27 krrp_queue_init(krrp_queue_t **queue, size_t obj_sz, size_t offset)
28 {
29 krrp_queue_t *qp;
30
31 VERIFY(queue != NULL && *queue == NULL);
32
33 qp = kmem_zalloc(sizeof (krrp_queue_t), KM_SLEEP);
34
35 list_create(&qp->list, obj_sz, offset);
36 qp->cnt = 0;
37 qp->force_return = B_FALSE;
38
39 mutex_init(&qp->mtx, NULL, MUTEX_DEFAULT, NULL);
40 cv_init(&qp->cv, NULL, CV_DEFAULT, NULL);
41
42 *queue = qp;
43 }
44
45 void
46 krrp_queue_fini(krrp_queue_t *queue)
47 {
48 mutex_enter(&queue->mtx);
49
50 VERIFY(queue->cnt == 0);
51 list_destroy(&queue->list);
52
53 mutex_exit(&queue->mtx);
54
55 cv_destroy(&queue->cv);
56 mutex_destroy(&queue->mtx);
57
58 kmem_free(queue, sizeof (krrp_queue_t));
59 }
60
61 size_t
62 krrp_queue_length(krrp_queue_t *queue)
63 {
64 size_t length = 0;
65
66 mutex_enter(&queue->mtx);
67 length = queue->cnt;
68 mutex_exit(&queue->mtx);
69
70 return (length);
71 }
72
73 void
74 krrp_queue_set_force_return(krrp_queue_t *queue)
75 {
76 mutex_enter(&queue->mtx);
77 queue->force_return = B_TRUE;
78 cv_broadcast(&queue->cv);
79 mutex_exit(&queue->mtx);
80 }
81
82 void
83 krrp_queue_put(krrp_queue_t *queue, void *obj)
84 {
85 ASSERT(obj != NULL);
86
87 mutex_enter(&queue->mtx);
88 list_insert_head(&queue->list, obj);
89 queue->cnt++;
90 cv_broadcast(&queue->cv);
91 mutex_exit(&queue->mtx);
92 }
93
94 void *
95 krrp_queue_get(krrp_queue_t *queue)
96 {
97 void *obj;
98 clock_t time_left = 0;
99
100 mutex_enter(&queue->mtx);
101
102 while ((obj = list_remove_tail(&queue->list)) == NULL) {
103 /*
104 * time_left < 0: timeout exceeded
105 */
106 if (queue->force_return || time_left < 0) {
107 mutex_exit(&queue->mtx);
108 return (NULL);
109 }
110
111 time_left = cv_reltimedwait(&queue->cv, &queue->mtx,
112 MSEC_TO_TICK(10), TR_CLOCK_TICK);
113 }
114
115 queue->cnt--;
116 mutex_exit(&queue->mtx);
117
118 return (obj);
119 }
120
121 void *
122 krrp_queue_get_no_wait(krrp_queue_t *queue)
123 {
124 void *obj;
125
126 mutex_enter(&queue->mtx);
127
128 obj = list_remove_tail(&queue->list);
129 if (obj != NULL)
130 queue->cnt--;
131
132 mutex_exit(&queue->mtx);
133
134 return (obj);
135 }