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