xref: /illumos-gate/usr/src/cmd/syslogd/queue.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0ea5e3a5Sjjj  * Common Development and Distribution License (the "License").
6*0ea5e3a5Sjjj  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*0ea5e3a5Sjjj  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <pthread.h>
277c478bd9Sstevel@tonic-gate #include <malloc.h>
287c478bd9Sstevel@tonic-gate #include <memory.h>
297c478bd9Sstevel@tonic-gate #include "dataq.h"
307c478bd9Sstevel@tonic-gate #include <assert.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #ifndef NDEBUG
337c478bd9Sstevel@tonic-gate static int
dataq_check(dataq_t * ptr)347c478bd9Sstevel@tonic-gate dataq_check(dataq_t *ptr)	/* call while holding lock! */
357c478bd9Sstevel@tonic-gate {
367c478bd9Sstevel@tonic-gate 	assert(ptr->num_data == ll_check(&ptr->data));
377c478bd9Sstevel@tonic-gate 	assert(ptr->num_waiters == ll_check(&ptr->waiters));
387c478bd9Sstevel@tonic-gate 	return (1);
397c478bd9Sstevel@tonic-gate }
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate int
dataq_init(dataq_t * ptr)437c478bd9Sstevel@tonic-gate dataq_init(dataq_t *ptr)
447c478bd9Sstevel@tonic-gate {
457c478bd9Sstevel@tonic-gate 	ptr->num_data = 0;
467c478bd9Sstevel@tonic-gate 	ptr->num_waiters = 0;
477c478bd9Sstevel@tonic-gate 	ll_init(&ptr->data);
487c478bd9Sstevel@tonic-gate 	ll_init(&ptr->waiters);
49*0ea5e3a5Sjjj 	(void) pthread_mutex_init(&ptr->lock, NULL);
507c478bd9Sstevel@tonic-gate 	assert((pthread_mutex_lock(&ptr->lock) == 0) &&
517c478bd9Sstevel@tonic-gate 		(dataq_check(ptr) == 1) &&
527c478bd9Sstevel@tonic-gate 		(pthread_mutex_unlock(&ptr->lock) == 0));
537c478bd9Sstevel@tonic-gate 	return (0);
547c478bd9Sstevel@tonic-gate }
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate int
dataq_enqueue(dataq_t * dataq,void * in)577c478bd9Sstevel@tonic-gate dataq_enqueue(dataq_t *dataq, void *in)
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	dataq_data_t *ptr = (dataq_data_t *)malloc(sizeof (*ptr));
607c478bd9Sstevel@tonic-gate 	dataq_waiter_t *sleeper;
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
637c478bd9Sstevel@tonic-gate 		return (-1);
647c478bd9Sstevel@tonic-gate 	ptr->data = in;
65*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&dataq->lock);
667c478bd9Sstevel@tonic-gate 	assert(dataq_check(dataq));
677c478bd9Sstevel@tonic-gate 	ll_enqueue(&dataq->data, &ptr->list);
687c478bd9Sstevel@tonic-gate 	dataq->num_data++;
697c478bd9Sstevel@tonic-gate 	if (dataq->num_waiters) {
707c478bd9Sstevel@tonic-gate 		/*LINTED*/
717c478bd9Sstevel@tonic-gate 		sleeper = (dataq_waiter_t *)ll_peek(&dataq->waiters);
727c478bd9Sstevel@tonic-gate 		sleeper->wakeup = 1;
73*0ea5e3a5Sjjj 		(void) pthread_cond_signal(&sleeper->cv);
747c478bd9Sstevel@tonic-gate 	}
757c478bd9Sstevel@tonic-gate 	assert(dataq_check(dataq));
76*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&dataq->lock);
777c478bd9Sstevel@tonic-gate 	return (0);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate int
dataq_dequeue(dataq_t * dataq,void ** outptr,int try)817c478bd9Sstevel@tonic-gate dataq_dequeue(dataq_t *dataq, void **outptr, int try)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	dataq_data_t *dptr;
847c478bd9Sstevel@tonic-gate 	dataq_waiter_t *sleeper;
857c478bd9Sstevel@tonic-gate 
86*0ea5e3a5Sjjj 	(void) pthread_mutex_lock(&dataq->lock);
877c478bd9Sstevel@tonic-gate 	if ((dataq->num_waiters > 0) ||
887c478bd9Sstevel@tonic-gate 	    ((dptr = (dataq_data_t *)ll_dequeue(&dataq->data)) == NULL)) {
897c478bd9Sstevel@tonic-gate 		dataq_waiter_t wait;
907c478bd9Sstevel@tonic-gate 		if (try) {
91*0ea5e3a5Sjjj 			(void) pthread_mutex_unlock(&dataq->lock);
927c478bd9Sstevel@tonic-gate 			return (1);
937c478bd9Sstevel@tonic-gate 		}
947c478bd9Sstevel@tonic-gate 		wait.wakeup = 0;
95*0ea5e3a5Sjjj 		(void) pthread_cond_init(&wait.cv, NULL);
967c478bd9Sstevel@tonic-gate 		dataq->num_waiters++;
977c478bd9Sstevel@tonic-gate 		ll_enqueue(&dataq->waiters, &wait.list);
987c478bd9Sstevel@tonic-gate 		while (wait.wakeup == 0)
99*0ea5e3a5Sjjj 			(void) pthread_cond_wait(&wait.cv, &dataq->lock);
100*0ea5e3a5Sjjj 		(void) ll_dequeue(&dataq->waiters);
1017c478bd9Sstevel@tonic-gate 		dataq->num_waiters--;
102*0ea5e3a5Sjjj 		(void) pthread_cond_destroy(&wait.cv);
1037c478bd9Sstevel@tonic-gate 		dptr = (dataq_data_t *)ll_dequeue(&dataq->data);
1047c478bd9Sstevel@tonic-gate 	}
1057c478bd9Sstevel@tonic-gate 	dataq->num_data--;
1067c478bd9Sstevel@tonic-gate 	if (dataq->num_data && dataq->num_waiters) {
1077c478bd9Sstevel@tonic-gate 		/*LINTED*/
1087c478bd9Sstevel@tonic-gate 		sleeper = (dataq_waiter_t *)ll_peek(&dataq->waiters);
1097c478bd9Sstevel@tonic-gate 		sleeper->wakeup = 1;
110*0ea5e3a5Sjjj 		(void) pthread_cond_signal(&sleeper->cv);
1117c478bd9Sstevel@tonic-gate 	}
112*0ea5e3a5Sjjj 	(void) pthread_mutex_unlock(&dataq->lock);
1137c478bd9Sstevel@tonic-gate 	*outptr = dptr->data;
1147c478bd9Sstevel@tonic-gate 	free(dptr);
1157c478bd9Sstevel@tonic-gate 	return (0);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate static void
dataq_data_destroy(void * p)1197c478bd9Sstevel@tonic-gate dataq_data_destroy(void * p)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	dataq_data_t *d = (dataq_data_t *)p;
1227c478bd9Sstevel@tonic-gate 	free(d->data);
1237c478bd9Sstevel@tonic-gate 	free(d);
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate static void
dataq_waiters_destroy(void * p)1277c478bd9Sstevel@tonic-gate dataq_waiters_destroy(void * p)
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate 	dataq_waiter_t *d = (dataq_waiter_t *)p;
130*0ea5e3a5Sjjj 	(void) pthread_cond_destroy(&d->cv);
1317c478bd9Sstevel@tonic-gate 	free(d);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate int
dataq_destroy(dataq_t * dataq)1357c478bd9Sstevel@tonic-gate dataq_destroy(dataq_t *dataq)
1367c478bd9Sstevel@tonic-gate {
137*0ea5e3a5Sjjj 	(void) pthread_mutex_destroy(&dataq->lock);
1387c478bd9Sstevel@tonic-gate 	ll_mapf(&dataq->data, dataq_data_destroy);
1397c478bd9Sstevel@tonic-gate 	ll_mapf(&dataq->waiters, dataq_waiters_destroy);
1407c478bd9Sstevel@tonic-gate 	return (0);
1417c478bd9Sstevel@tonic-gate }
142