xref: /illumos-gate/usr/src/cmd/ndmpd/tlm/tlm_buffers.c (revision 2654012f)
1*2654012fSReza Sabdar /*
2*2654012fSReza Sabdar  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3*2654012fSReza Sabdar  * Use is subject to license terms.
4*2654012fSReza Sabdar  */
5*2654012fSReza Sabdar 
6*2654012fSReza Sabdar /*
7*2654012fSReza Sabdar  * BSD 3 Clause License
8*2654012fSReza Sabdar  *
9*2654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
10*2654012fSReza Sabdar  *
11*2654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
12*2654012fSReza Sabdar  * modification, are permitted provided that the following conditions
13*2654012fSReza Sabdar  * are met:
14*2654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
15*2654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
16*2654012fSReza Sabdar  *
17*2654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
18*2654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
19*2654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
20*2654012fSReza Sabdar  *	  distribution.
21*2654012fSReza Sabdar  *
22*2654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
23*2654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
24*2654012fSReza Sabdar  *	  products derived from this software without specific prior written
25*2654012fSReza Sabdar  *	  permission.
26*2654012fSReza Sabdar  *
27*2654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28*2654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29*2654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30*2654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31*2654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32*2654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33*2654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*2654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*2654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36*2654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37*2654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
38*2654012fSReza Sabdar  */
39*2654012fSReza Sabdar #include <stdio.h>
40*2654012fSReza Sabdar #include <stdlib.h>
41*2654012fSReza Sabdar #include <sys/errno.h>
42*2654012fSReza Sabdar #include <string.h>
43*2654012fSReza Sabdar #include <unistd.h>
44*2654012fSReza Sabdar #include <pthread.h>
45*2654012fSReza Sabdar #include <synch.h>
46*2654012fSReza Sabdar #include <tlm_buffers.h>
47*2654012fSReza Sabdar #include <tlm.h>
48*2654012fSReza Sabdar #include "tlm_proto.h"
49*2654012fSReza Sabdar 
50*2654012fSReza Sabdar 
51*2654012fSReza Sabdar /*
52*2654012fSReza Sabdar  * tlm_allocate_buffers
53*2654012fSReza Sabdar  *
54*2654012fSReza Sabdar  * build a set of buffers
55*2654012fSReza Sabdar  */
56*2654012fSReza Sabdar tlm_buffers_t *
tlm_allocate_buffers(boolean_t write,long xfer_size)57*2654012fSReza Sabdar tlm_allocate_buffers(boolean_t write, long xfer_size)
58*2654012fSReza Sabdar {
59*2654012fSReza Sabdar 	tlm_buffers_t *buffers = ndmp_malloc(sizeof (tlm_buffers_t));
60*2654012fSReza Sabdar 	int	buf;
61*2654012fSReza Sabdar 
62*2654012fSReza Sabdar 	if (buffers == 0)
63*2654012fSReza Sabdar 		return (0);
64*2654012fSReza Sabdar 
65*2654012fSReza Sabdar 	for (buf = 0; buf < TLM_TAPE_BUFFERS; buf++) {
66*2654012fSReza Sabdar 		buffers->tbs_buffer[buf].tb_buffer_data =
67*2654012fSReza Sabdar 		    ndmp_malloc(xfer_size);
68*2654012fSReza Sabdar 		if (buffers->tbs_buffer[buf].tb_buffer_data == 0) {
69*2654012fSReza Sabdar 			int	i;
70*2654012fSReza Sabdar 
71*2654012fSReza Sabdar 			/* Memory allocation failed. Give everything back */
72*2654012fSReza Sabdar 			for (i = 0; i < buf; i++)
73*2654012fSReza Sabdar 				free(buffers->tbs_buffer[i].tb_buffer_data);
74*2654012fSReza Sabdar 
75*2654012fSReza Sabdar 			free(buffers);
76*2654012fSReza Sabdar 			return (0);
77*2654012fSReza Sabdar 		} else {
78*2654012fSReza Sabdar 			buffers->tbs_buffer[buf].tb_buffer_size = (write)
79*2654012fSReza Sabdar 			    ? xfer_size : 0;
80*2654012fSReza Sabdar 			buffers->tbs_buffer[buf].tb_full = FALSE;
81*2654012fSReza Sabdar 			buffers->tbs_buffer[buf].tb_eof = FALSE;
82*2654012fSReza Sabdar 			buffers->tbs_buffer[buf].tb_eot = FALSE;
83*2654012fSReza Sabdar 			buffers->tbs_buffer[buf].tb_errno = 0;
84*2654012fSReza Sabdar 			buffers->tbs_buffer[buf].tb_buffer_spot = 0;
85*2654012fSReza Sabdar 		}
86*2654012fSReza Sabdar 
87*2654012fSReza Sabdar 	}
88*2654012fSReza Sabdar 
89*2654012fSReza Sabdar 	(void) mutex_init(&buffers->tbs_mtx, 0, NULL);
90*2654012fSReza Sabdar 	(void) cond_init(&buffers->tbs_in_cv, 0, NULL);
91*2654012fSReza Sabdar 	(void) cond_init(&buffers->tbs_out_cv, 0, NULL);
92*2654012fSReza Sabdar 
93*2654012fSReza Sabdar 	buffers->tbs_data_transfer_size = xfer_size;
94*2654012fSReza Sabdar 	buffers->tbs_ref = 1;
95*2654012fSReza Sabdar 	return (buffers);
96*2654012fSReza Sabdar }
97*2654012fSReza Sabdar 
98*2654012fSReza Sabdar /*
99*2654012fSReza Sabdar  * tlm_release_buffers
100*2654012fSReza Sabdar  *
101*2654012fSReza Sabdar  * give all memory back to the OS
102*2654012fSReza Sabdar  */
103*2654012fSReza Sabdar void
tlm_release_buffers(tlm_buffers_t * buffers)104*2654012fSReza Sabdar tlm_release_buffers(tlm_buffers_t *buffers)
105*2654012fSReza Sabdar {
106*2654012fSReza Sabdar 	int i;
107*2654012fSReza Sabdar 
108*2654012fSReza Sabdar 	if (buffers != NULL) {
109*2654012fSReza Sabdar 		tlm_buffer_release_in_buf(buffers);
110*2654012fSReza Sabdar 		tlm_buffer_release_out_buf(buffers);
111*2654012fSReza Sabdar 
112*2654012fSReza Sabdar 		(void) mutex_lock(&buffers->tbs_mtx);
113*2654012fSReza Sabdar 
114*2654012fSReza Sabdar 		if (--buffers->tbs_ref <= 0) {
115*2654012fSReza Sabdar 			for (i = 0; i < TLM_TAPE_BUFFERS; i++)
116*2654012fSReza Sabdar 				free(buffers->tbs_buffer[i].tb_buffer_data);
117*2654012fSReza Sabdar 
118*2654012fSReza Sabdar 		}
119*2654012fSReza Sabdar 
120*2654012fSReza Sabdar 		(void) cond_destroy(&buffers->tbs_in_cv);
121*2654012fSReza Sabdar 		(void) cond_destroy(&buffers->tbs_out_cv);
122*2654012fSReza Sabdar 		(void) mutex_unlock(&buffers->tbs_mtx);
123*2654012fSReza Sabdar 		(void) mutex_destroy(&buffers->tbs_mtx);
124*2654012fSReza Sabdar 		free(buffers);
125*2654012fSReza Sabdar 	}
126*2654012fSReza Sabdar }
127*2654012fSReza Sabdar 
128*2654012fSReza Sabdar /*
129*2654012fSReza Sabdar  * tlm_buffer_mark_empty
130*2654012fSReza Sabdar  *
131*2654012fSReza Sabdar  * Mark a buffer empty and clear its flags. No lock is take here:
132*2654012fSReza Sabdar  * the buffer should be marked empty before it is released for use
133*2654012fSReza Sabdar  * by another thread.
134*2654012fSReza Sabdar  */
135*2654012fSReza Sabdar void
tlm_buffer_mark_empty(tlm_buffer_t * buf)136*2654012fSReza Sabdar tlm_buffer_mark_empty(tlm_buffer_t *buf)
137*2654012fSReza Sabdar {
138*2654012fSReza Sabdar 	if (buf == NULL)
139*2654012fSReza Sabdar 		return;
140*2654012fSReza Sabdar 
141*2654012fSReza Sabdar 	buf->tb_full = buf->tb_eof = buf->tb_eot = FALSE;
142*2654012fSReza Sabdar 	buf->tb_errno = 0;
143*2654012fSReza Sabdar }
144*2654012fSReza Sabdar 
145*2654012fSReza Sabdar 
146*2654012fSReza Sabdar /*
147*2654012fSReza Sabdar  * tlm_buffer_advance_in_idx
148*2654012fSReza Sabdar  *
149*2654012fSReza Sabdar  * Advance the input index of the buffers(round-robin) and return pointer
150*2654012fSReza Sabdar  * to the next buffer in the buffer pool.
151*2654012fSReza Sabdar  */
152*2654012fSReza Sabdar tlm_buffer_t *
tlm_buffer_advance_in_idx(tlm_buffers_t * bufs)153*2654012fSReza Sabdar tlm_buffer_advance_in_idx(tlm_buffers_t *bufs)
154*2654012fSReza Sabdar {
155*2654012fSReza Sabdar 	if (bufs == NULL)
156*2654012fSReza Sabdar 		return (NULL);
157*2654012fSReza Sabdar 
158*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
159*2654012fSReza Sabdar 	if (++bufs->tbs_buffer_in >= TLM_TAPE_BUFFERS)
160*2654012fSReza Sabdar 		bufs->tbs_buffer_in = 0;
161*2654012fSReza Sabdar 
162*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
163*2654012fSReza Sabdar 	return (&bufs->tbs_buffer[bufs->tbs_buffer_in]);
164*2654012fSReza Sabdar }
165*2654012fSReza Sabdar 
166*2654012fSReza Sabdar 
167*2654012fSReza Sabdar /*
168*2654012fSReza Sabdar  * tlm_buffer_advance_out_idx
169*2654012fSReza Sabdar  *
170*2654012fSReza Sabdar  * Advance the output index of the buffers(round-robin) and return pointer
171*2654012fSReza Sabdar  * to the next buffer in the buffer pool.
172*2654012fSReza Sabdar  */
173*2654012fSReza Sabdar tlm_buffer_t *
tlm_buffer_advance_out_idx(tlm_buffers_t * bufs)174*2654012fSReza Sabdar tlm_buffer_advance_out_idx(tlm_buffers_t *bufs)
175*2654012fSReza Sabdar {
176*2654012fSReza Sabdar 	if (bufs == NULL)
177*2654012fSReza Sabdar 		return (NULL);
178*2654012fSReza Sabdar 
179*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
180*2654012fSReza Sabdar 	if (++bufs->tbs_buffer_out >= TLM_TAPE_BUFFERS)
181*2654012fSReza Sabdar 		bufs->tbs_buffer_out = 0;
182*2654012fSReza Sabdar 
183*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
184*2654012fSReza Sabdar 	return (&bufs->tbs_buffer[bufs->tbs_buffer_out]);
185*2654012fSReza Sabdar }
186*2654012fSReza Sabdar 
187*2654012fSReza Sabdar 
188*2654012fSReza Sabdar /*
189*2654012fSReza Sabdar  * tlm_buffer_in_buf
190*2654012fSReza Sabdar  *
191*2654012fSReza Sabdar  * Return pointer to the next buffer in the buffer pool.
192*2654012fSReza Sabdar  */
193*2654012fSReza Sabdar tlm_buffer_t *
tlm_buffer_in_buf(tlm_buffers_t * bufs,int * idx)194*2654012fSReza Sabdar tlm_buffer_in_buf(tlm_buffers_t *bufs, int *idx)
195*2654012fSReza Sabdar {
196*2654012fSReza Sabdar 	tlm_buffer_t *ret;
197*2654012fSReza Sabdar 
198*2654012fSReza Sabdar 	if (bufs == NULL)
199*2654012fSReza Sabdar 		return (NULL);
200*2654012fSReza Sabdar 
201*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
202*2654012fSReza Sabdar 	ret = &bufs->tbs_buffer[bufs->tbs_buffer_in];
203*2654012fSReza Sabdar 	if (idx)
204*2654012fSReza Sabdar 		*idx = bufs->tbs_buffer_in;
205*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
206*2654012fSReza Sabdar 	return (ret);
207*2654012fSReza Sabdar }
208*2654012fSReza Sabdar 
209*2654012fSReza Sabdar 
210*2654012fSReza Sabdar /*
211*2654012fSReza Sabdar  * tlm_buffer_out_buf
212*2654012fSReza Sabdar  *
213*2654012fSReza Sabdar  * Return pointer to the next buffer in the buffer pool.
214*2654012fSReza Sabdar  */
215*2654012fSReza Sabdar tlm_buffer_t *
tlm_buffer_out_buf(tlm_buffers_t * bufs,int * idx)216*2654012fSReza Sabdar tlm_buffer_out_buf(tlm_buffers_t *bufs, int *idx)
217*2654012fSReza Sabdar {
218*2654012fSReza Sabdar 	tlm_buffer_t *ret;
219*2654012fSReza Sabdar 
220*2654012fSReza Sabdar 	if (bufs == NULL)
221*2654012fSReza Sabdar 		return (NULL);
222*2654012fSReza Sabdar 
223*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
224*2654012fSReza Sabdar 	ret = &bufs->tbs_buffer[bufs->tbs_buffer_out];
225*2654012fSReza Sabdar 	if (idx)
226*2654012fSReza Sabdar 		*idx = bufs->tbs_buffer_out;
227*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
228*2654012fSReza Sabdar 	return (ret);
229*2654012fSReza Sabdar }
230*2654012fSReza Sabdar 
231*2654012fSReza Sabdar 
232*2654012fSReza Sabdar /*
233*2654012fSReza Sabdar  * tlm_buffer_release_in_buf
234*2654012fSReza Sabdar  *
235*2654012fSReza Sabdar  * Another buffer is filled. Wake up the consumer if it's waiting for it.
236*2654012fSReza Sabdar  */
237*2654012fSReza Sabdar void
tlm_buffer_release_in_buf(tlm_buffers_t * bufs)238*2654012fSReza Sabdar tlm_buffer_release_in_buf(tlm_buffers_t *bufs)
239*2654012fSReza Sabdar {
240*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
241*2654012fSReza Sabdar 	bufs->tbs_flags |= TLM_BUF_IN_READY;
242*2654012fSReza Sabdar 	(void) cond_signal(&bufs->tbs_in_cv);
243*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
244*2654012fSReza Sabdar }
245*2654012fSReza Sabdar 
246*2654012fSReza Sabdar 
247*2654012fSReza Sabdar /*
248*2654012fSReza Sabdar  * tlm_buffer_release_out_buf
249*2654012fSReza Sabdar  *
250*2654012fSReza Sabdar  * A buffer is used. Wake up the producer to re-fill a buffer if it's waiting
251*2654012fSReza Sabdar  * for the buffer to be used.
252*2654012fSReza Sabdar  */
253*2654012fSReza Sabdar void
tlm_buffer_release_out_buf(tlm_buffers_t * bufs)254*2654012fSReza Sabdar tlm_buffer_release_out_buf(tlm_buffers_t *bufs)
255*2654012fSReza Sabdar {
256*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
257*2654012fSReza Sabdar 	bufs->tbs_flags |= TLM_BUF_OUT_READY;
258*2654012fSReza Sabdar 	(void) cond_signal(&bufs->tbs_out_cv);
259*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
260*2654012fSReza Sabdar }
261*2654012fSReza Sabdar 
262*2654012fSReza Sabdar /*
263*2654012fSReza Sabdar  * tlm_buffer_in_buf_wait
264*2654012fSReza Sabdar  *
265*2654012fSReza Sabdar  * Wait for the input buffer to get available.
266*2654012fSReza Sabdar  */
267*2654012fSReza Sabdar void
tlm_buffer_in_buf_wait(tlm_buffers_t * bufs)268*2654012fSReza Sabdar tlm_buffer_in_buf_wait(tlm_buffers_t *bufs)
269*2654012fSReza Sabdar 
270*2654012fSReza Sabdar {
271*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
272*2654012fSReza Sabdar 
273*2654012fSReza Sabdar 	while ((bufs->tbs_flags & TLM_BUF_IN_READY) == 0)
274*2654012fSReza Sabdar 		(void) cond_wait(&bufs->tbs_in_cv, &bufs->tbs_mtx);
275*2654012fSReza Sabdar 
276*2654012fSReza Sabdar 	bufs->tbs_flags &= ~TLM_BUF_IN_READY;
277*2654012fSReza Sabdar 
278*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
279*2654012fSReza Sabdar }
280*2654012fSReza Sabdar 
281*2654012fSReza Sabdar /*
282*2654012fSReza Sabdar  * tlm_buffer_setup_timer
283*2654012fSReza Sabdar  *
284*2654012fSReza Sabdar  * Set up the time out value.
285*2654012fSReza Sabdar  */
286*2654012fSReza Sabdar static inline void
tlm_buffer_setup_timer(timestruc_t * timo,unsigned milli_timo)287*2654012fSReza Sabdar tlm_buffer_setup_timer(timestruc_t *timo, unsigned milli_timo)
288*2654012fSReza Sabdar {
289*2654012fSReza Sabdar 	if (milli_timo == 0)
290*2654012fSReza Sabdar 		milli_timo = 1;
291*2654012fSReza Sabdar 
292*2654012fSReza Sabdar 	if (milli_timo / 1000)
293*2654012fSReza Sabdar 		timo->tv_sec = (milli_timo / 1000);
294*2654012fSReza Sabdar 	else
295*2654012fSReza Sabdar 		timo->tv_sec = 0;
296*2654012fSReza Sabdar 	timo->tv_nsec = (milli_timo % 1000) * 1000000L;
297*2654012fSReza Sabdar }
298*2654012fSReza Sabdar 
299*2654012fSReza Sabdar 
300*2654012fSReza Sabdar /*
301*2654012fSReza Sabdar  * tlm_buffer_in_buf_timed_wait
302*2654012fSReza Sabdar  *
303*2654012fSReza Sabdar  * Wait for the input buffer to get ready with a time out.
304*2654012fSReza Sabdar  */
305*2654012fSReza Sabdar void
tlm_buffer_in_buf_timed_wait(tlm_buffers_t * bufs,unsigned int milli_timo)306*2654012fSReza Sabdar tlm_buffer_in_buf_timed_wait(tlm_buffers_t *bufs, unsigned int milli_timo)
307*2654012fSReza Sabdar 
308*2654012fSReza Sabdar {
309*2654012fSReza Sabdar 	timestruc_t timo;
310*2654012fSReza Sabdar 
311*2654012fSReza Sabdar 	tlm_buffer_setup_timer(&timo, milli_timo);
312*2654012fSReza Sabdar 
313*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
314*2654012fSReza Sabdar 
315*2654012fSReza Sabdar 	(void) cond_reltimedwait(&bufs->tbs_in_cv, &bufs->tbs_mtx, &timo);
316*2654012fSReza Sabdar 
317*2654012fSReza Sabdar 	/*
318*2654012fSReza Sabdar 	 * TLM_BUF_IN_READY doesn't matter for timedwait but clear
319*2654012fSReza Sabdar 	 * it here so that cond_wait doesn't get the wrong result.
320*2654012fSReza Sabdar 	 */
321*2654012fSReza Sabdar 	bufs->tbs_flags &= ~TLM_BUF_IN_READY;
322*2654012fSReza Sabdar 
323*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
324*2654012fSReza Sabdar }
325*2654012fSReza Sabdar 
326*2654012fSReza Sabdar 
327*2654012fSReza Sabdar /*
328*2654012fSReza Sabdar  * tlm_buffer_out_buf_timed_wait
329*2654012fSReza Sabdar  *
330*2654012fSReza Sabdar  * Wait for the output buffer to get ready with a time out.
331*2654012fSReza Sabdar  */
332*2654012fSReza Sabdar void
tlm_buffer_out_buf_timed_wait(tlm_buffers_t * bufs,unsigned int milli_timo)333*2654012fSReza Sabdar tlm_buffer_out_buf_timed_wait(tlm_buffers_t *bufs, unsigned int milli_timo)
334*2654012fSReza Sabdar {
335*2654012fSReza Sabdar 	timestruc_t timo;
336*2654012fSReza Sabdar 
337*2654012fSReza Sabdar 	tlm_buffer_setup_timer(&timo, milli_timo);
338*2654012fSReza Sabdar 
339*2654012fSReza Sabdar 	(void) mutex_lock(&bufs->tbs_mtx);
340*2654012fSReza Sabdar 
341*2654012fSReza Sabdar 	(void) cond_reltimedwait(&bufs->tbs_out_cv, &bufs->tbs_mtx, &timo);
342*2654012fSReza Sabdar 
343*2654012fSReza Sabdar 	/*
344*2654012fSReza Sabdar 	 * TLM_BUF_OUT_READY doesn't matter for timedwait but clear
345*2654012fSReza Sabdar 	 * it here so that cond_wait doesn't get the wrong result.
346*2654012fSReza Sabdar 	 */
347*2654012fSReza Sabdar 	bufs->tbs_flags &= ~TLM_BUF_OUT_READY;
348*2654012fSReza Sabdar 
349*2654012fSReza Sabdar 	(void) mutex_unlock(&bufs->tbs_mtx);
350*2654012fSReza Sabdar }
351*2654012fSReza Sabdar 
352*2654012fSReza Sabdar 
353*2654012fSReza Sabdar /*
354*2654012fSReza Sabdar  * tlm_cmd_wait
355*2654012fSReza Sabdar  *
356*2654012fSReza Sabdar  * TLM command synchronization typically use by command
357*2654012fSReza Sabdar  * parent threads to wait for launched threads to initialize.
358*2654012fSReza Sabdar  */
359*2654012fSReza Sabdar void
tlm_cmd_wait(tlm_cmd_t * cmd,uint32_t event_type)360*2654012fSReza Sabdar tlm_cmd_wait(tlm_cmd_t *cmd, uint32_t event_type)
361*2654012fSReza Sabdar {
362*2654012fSReza Sabdar 	(void) mutex_lock(&cmd->tc_mtx);
363*2654012fSReza Sabdar 
364*2654012fSReza Sabdar 	while ((cmd->tc_flags & event_type) == 0)
365*2654012fSReza Sabdar 		(void) cond_wait(&cmd->tc_cv, &cmd->tc_mtx);
366*2654012fSReza Sabdar 
367*2654012fSReza Sabdar 	cmd->tc_flags &= ~event_type;
368*2654012fSReza Sabdar 	(void) mutex_unlock(&cmd->tc_mtx);
369*2654012fSReza Sabdar }
370*2654012fSReza Sabdar 
371*2654012fSReza Sabdar 
372*2654012fSReza Sabdar /*
373*2654012fSReza Sabdar  * tlm_cmd_signal
374*2654012fSReza Sabdar  *
375*2654012fSReza Sabdar  * TLM command synchronization typically use by launched threads
376*2654012fSReza Sabdar  * to unleash the parent thread.
377*2654012fSReza Sabdar  */
378*2654012fSReza Sabdar void
tlm_cmd_signal(tlm_cmd_t * cmd,uint32_t event_type)379*2654012fSReza Sabdar tlm_cmd_signal(tlm_cmd_t *cmd, uint32_t event_type)
380*2654012fSReza Sabdar {
381*2654012fSReza Sabdar 	(void) mutex_lock(&cmd->tc_mtx);
382*2654012fSReza Sabdar 
383*2654012fSReza Sabdar 	cmd->tc_flags |= event_type;
384*2654012fSReza Sabdar 	(void) cond_signal(&cmd->tc_cv);
385*2654012fSReza Sabdar 
386*2654012fSReza Sabdar 	(void) mutex_unlock(&cmd->tc_mtx);
387*2654012fSReza Sabdar }
388