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 #pragma ident "%Z%%M% %I% %E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <pthread.h>
297c478bd9Sstevel@tonic-gate #include <malloc.h>
307c478bd9Sstevel@tonic-gate #include <memory.h>
317c478bd9Sstevel@tonic-gate #include "dataq.h"
327c478bd9Sstevel@tonic-gate #include <assert.h>
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate #ifndef NDEBUG
357c478bd9Sstevel@tonic-gate static int
dataq_check(dataq_t * ptr)367c478bd9Sstevel@tonic-gate dataq_check(dataq_t *ptr) /* call while holding lock! */
377c478bd9Sstevel@tonic-gate {
387c478bd9Sstevel@tonic-gate assert(ptr->num_data == ll_check(&ptr->data));
397c478bd9Sstevel@tonic-gate assert(ptr->num_waiters == ll_check(&ptr->waiters));
407c478bd9Sstevel@tonic-gate return (1);
417c478bd9Sstevel@tonic-gate }
427c478bd9Sstevel@tonic-gate #endif
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate int
dataq_init(dataq_t * ptr)457c478bd9Sstevel@tonic-gate dataq_init(dataq_t *ptr)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate ptr->num_data = 0;
487c478bd9Sstevel@tonic-gate ptr->num_waiters = 0;
497c478bd9Sstevel@tonic-gate ll_init(&ptr->data);
507c478bd9Sstevel@tonic-gate ll_init(&ptr->waiters);
51*0ea5e3a5Sjjj (void) pthread_mutex_init(&ptr->lock, NULL);
527c478bd9Sstevel@tonic-gate assert((pthread_mutex_lock(&ptr->lock) == 0) &&
537c478bd9Sstevel@tonic-gate (dataq_check(ptr) == 1) &&
547c478bd9Sstevel@tonic-gate (pthread_mutex_unlock(&ptr->lock) == 0));
557c478bd9Sstevel@tonic-gate return (0);
567c478bd9Sstevel@tonic-gate }
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate int
dataq_enqueue(dataq_t * dataq,void * in)597c478bd9Sstevel@tonic-gate dataq_enqueue(dataq_t *dataq, void *in)
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate dataq_data_t *ptr = (dataq_data_t *)malloc(sizeof (*ptr));
627c478bd9Sstevel@tonic-gate dataq_waiter_t *sleeper;
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate if (ptr == NULL)
657c478bd9Sstevel@tonic-gate return (-1);
667c478bd9Sstevel@tonic-gate ptr->data = in;
67*0ea5e3a5Sjjj (void) pthread_mutex_lock(&dataq->lock);
687c478bd9Sstevel@tonic-gate assert(dataq_check(dataq));
697c478bd9Sstevel@tonic-gate ll_enqueue(&dataq->data, &ptr->list);
707c478bd9Sstevel@tonic-gate dataq->num_data++;
717c478bd9Sstevel@tonic-gate if (dataq->num_waiters) {
727c478bd9Sstevel@tonic-gate /*LINTED*/
737c478bd9Sstevel@tonic-gate sleeper = (dataq_waiter_t *)ll_peek(&dataq->waiters);
747c478bd9Sstevel@tonic-gate sleeper->wakeup = 1;
75*0ea5e3a5Sjjj (void) pthread_cond_signal(&sleeper->cv);
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate assert(dataq_check(dataq));
78*0ea5e3a5Sjjj (void) pthread_mutex_unlock(&dataq->lock);
797c478bd9Sstevel@tonic-gate return (0);
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate int
dataq_dequeue(dataq_t * dataq,void ** outptr,int try)837c478bd9Sstevel@tonic-gate dataq_dequeue(dataq_t *dataq, void **outptr, int try)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate dataq_data_t *dptr;
867c478bd9Sstevel@tonic-gate dataq_waiter_t *sleeper;
877c478bd9Sstevel@tonic-gate
88*0ea5e3a5Sjjj (void) pthread_mutex_lock(&dataq->lock);
897c478bd9Sstevel@tonic-gate if ((dataq->num_waiters > 0) ||
907c478bd9Sstevel@tonic-gate ((dptr = (dataq_data_t *)ll_dequeue(&dataq->data)) == NULL)) {
917c478bd9Sstevel@tonic-gate dataq_waiter_t wait;
927c478bd9Sstevel@tonic-gate if (try) {
93*0ea5e3a5Sjjj (void) pthread_mutex_unlock(&dataq->lock);
947c478bd9Sstevel@tonic-gate return (1);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate wait.wakeup = 0;
97*0ea5e3a5Sjjj (void) pthread_cond_init(&wait.cv, NULL);
987c478bd9Sstevel@tonic-gate dataq->num_waiters++;
997c478bd9Sstevel@tonic-gate ll_enqueue(&dataq->waiters, &wait.list);
1007c478bd9Sstevel@tonic-gate while (wait.wakeup == 0)
101*0ea5e3a5Sjjj (void) pthread_cond_wait(&wait.cv, &dataq->lock);
102*0ea5e3a5Sjjj (void) ll_dequeue(&dataq->waiters);
1037c478bd9Sstevel@tonic-gate dataq->num_waiters--;
104*0ea5e3a5Sjjj (void) pthread_cond_destroy(&wait.cv);
1057c478bd9Sstevel@tonic-gate dptr = (dataq_data_t *)ll_dequeue(&dataq->data);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate dataq->num_data--;
1087c478bd9Sstevel@tonic-gate if (dataq->num_data && dataq->num_waiters) {
1097c478bd9Sstevel@tonic-gate /*LINTED*/
1107c478bd9Sstevel@tonic-gate sleeper = (dataq_waiter_t *)ll_peek(&dataq->waiters);
1117c478bd9Sstevel@tonic-gate sleeper->wakeup = 1;
112*0ea5e3a5Sjjj (void) pthread_cond_signal(&sleeper->cv);
1137c478bd9Sstevel@tonic-gate }
114*0ea5e3a5Sjjj (void) pthread_mutex_unlock(&dataq->lock);
1157c478bd9Sstevel@tonic-gate *outptr = dptr->data;
1167c478bd9Sstevel@tonic-gate free(dptr);
1177c478bd9Sstevel@tonic-gate return (0);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate static void
dataq_data_destroy(void * p)1217c478bd9Sstevel@tonic-gate dataq_data_destroy(void * p)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate dataq_data_t *d = (dataq_data_t *)p;
1247c478bd9Sstevel@tonic-gate free(d->data);
1257c478bd9Sstevel@tonic-gate free(d);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate static void
dataq_waiters_destroy(void * p)1297c478bd9Sstevel@tonic-gate dataq_waiters_destroy(void * p)
1307c478bd9Sstevel@tonic-gate {
1317c478bd9Sstevel@tonic-gate dataq_waiter_t *d = (dataq_waiter_t *)p;
132*0ea5e3a5Sjjj (void) pthread_cond_destroy(&d->cv);
1337c478bd9Sstevel@tonic-gate free(d);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate int
dataq_destroy(dataq_t * dataq)1377c478bd9Sstevel@tonic-gate dataq_destroy(dataq_t *dataq)
1387c478bd9Sstevel@tonic-gate {
139*0ea5e3a5Sjjj (void) pthread_mutex_destroy(&dataq->lock);
1407c478bd9Sstevel@tonic-gate ll_mapf(&dataq->data, dataq_data_destroy);
1417c478bd9Sstevel@tonic-gate ll_mapf(&dataq->waiters, dataq_waiters_destroy);
1427c478bd9Sstevel@tonic-gate return (0);
1437c478bd9Sstevel@tonic-gate }
144