xref: /illumos-gate/usr/src/cmd/syslogd/queue.c (revision 2a8bcb4e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <pthread.h>
27 #include <malloc.h>
28 #include <memory.h>
29 #include "dataq.h"
30 #include <assert.h>
31 
32 #ifndef NDEBUG
33 static int
dataq_check(dataq_t * ptr)34 dataq_check(dataq_t *ptr)	/* call while holding lock! */
35 {
36 	assert(ptr->num_data == ll_check(&ptr->data));
37 	assert(ptr->num_waiters == ll_check(&ptr->waiters));
38 	return (1);
39 }
40 #endif
41 
42 int
dataq_init(dataq_t * ptr)43 dataq_init(dataq_t *ptr)
44 {
45 	ptr->num_data = 0;
46 	ptr->num_waiters = 0;
47 	ll_init(&ptr->data);
48 	ll_init(&ptr->waiters);
49 	(void) pthread_mutex_init(&ptr->lock, NULL);
50 	assert((pthread_mutex_lock(&ptr->lock) == 0) &&
51 		(dataq_check(ptr) == 1) &&
52 		(pthread_mutex_unlock(&ptr->lock) == 0));
53 	return (0);
54 }
55 
56 int
dataq_enqueue(dataq_t * dataq,void * in)57 dataq_enqueue(dataq_t *dataq, void *in)
58 {
59 	dataq_data_t *ptr = (dataq_data_t *)malloc(sizeof (*ptr));
60 	dataq_waiter_t *sleeper;
61 
62 	if (ptr == NULL)
63 		return (-1);
64 	ptr->data = in;
65 	(void) pthread_mutex_lock(&dataq->lock);
66 	assert(dataq_check(dataq));
67 	ll_enqueue(&dataq->data, &ptr->list);
68 	dataq->num_data++;
69 	if (dataq->num_waiters) {
70 		/*LINTED*/
71 		sleeper = (dataq_waiter_t *)ll_peek(&dataq->waiters);
72 		sleeper->wakeup = 1;
73 		(void) pthread_cond_signal(&sleeper->cv);
74 	}
75 	assert(dataq_check(dataq));
76 	(void) pthread_mutex_unlock(&dataq->lock);
77 	return (0);
78 }
79 
80 int
dataq_dequeue(dataq_t * dataq,void ** outptr,int try)81 dataq_dequeue(dataq_t *dataq, void **outptr, int try)
82 {
83 	dataq_data_t *dptr;
84 	dataq_waiter_t *sleeper;
85 
86 	(void) pthread_mutex_lock(&dataq->lock);
87 	if ((dataq->num_waiters > 0) ||
88 	    ((dptr = (dataq_data_t *)ll_dequeue(&dataq->data)) == NULL)) {
89 		dataq_waiter_t wait;
90 		if (try) {
91 			(void) pthread_mutex_unlock(&dataq->lock);
92 			return (1);
93 		}
94 		wait.wakeup = 0;
95 		(void) pthread_cond_init(&wait.cv, NULL);
96 		dataq->num_waiters++;
97 		ll_enqueue(&dataq->waiters, &wait.list);
98 		while (wait.wakeup == 0)
99 			(void) pthread_cond_wait(&wait.cv, &dataq->lock);
100 		(void) ll_dequeue(&dataq->waiters);
101 		dataq->num_waiters--;
102 		(void) pthread_cond_destroy(&wait.cv);
103 		dptr = (dataq_data_t *)ll_dequeue(&dataq->data);
104 	}
105 	dataq->num_data--;
106 	if (dataq->num_data && dataq->num_waiters) {
107 		/*LINTED*/
108 		sleeper = (dataq_waiter_t *)ll_peek(&dataq->waiters);
109 		sleeper->wakeup = 1;
110 		(void) pthread_cond_signal(&sleeper->cv);
111 	}
112 	(void) pthread_mutex_unlock(&dataq->lock);
113 	*outptr = dptr->data;
114 	free(dptr);
115 	return (0);
116 }
117 
118 static void
dataq_data_destroy(void * p)119 dataq_data_destroy(void * p)
120 {
121 	dataq_data_t *d = (dataq_data_t *)p;
122 	free(d->data);
123 	free(d);
124 }
125 
126 static void
dataq_waiters_destroy(void * p)127 dataq_waiters_destroy(void * p)
128 {
129 	dataq_waiter_t *d = (dataq_waiter_t *)p;
130 	(void) pthread_cond_destroy(&d->cv);
131 	free(d);
132 }
133 
134 int
dataq_destroy(dataq_t * dataq)135 dataq_destroy(dataq_t *dataq)
136 {
137 	(void) pthread_mutex_destroy(&dataq->lock);
138 	ll_mapf(&dataq->data, dataq_data_destroy);
139 	ll_mapf(&dataq->waiters, dataq_waiters_destroy);
140 	return (0);
141 }
142