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