8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ndmpd / tlm / tlm_buffers.c
blob814ec3d31707f10ad6cb703379f4cc9f5e7e248b
1 /*
2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
6 /*
7 * BSD 3 Clause License
9 * Copyright (c) 2007, The Storage Networking Industry Association.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
25 * permission.
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <sys/errno.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <pthread.h>
45 #include <synch.h>
46 #include <tlm_buffers.h>
47 #include <tlm.h>
48 #include "tlm_proto.h"
52 * tlm_allocate_buffers
54 * build a set of buffers
56 tlm_buffers_t *
57 tlm_allocate_buffers(boolean_t write, long xfer_size)
59 tlm_buffers_t *buffers = ndmp_malloc(sizeof (tlm_buffers_t));
60 int buf;
62 if (buffers == 0)
63 return (0);
65 for (buf = 0; buf < TLM_TAPE_BUFFERS; buf++) {
66 buffers->tbs_buffer[buf].tb_buffer_data =
67 ndmp_malloc(xfer_size);
68 if (buffers->tbs_buffer[buf].tb_buffer_data == 0) {
69 int i;
71 /* Memory allocation failed. Give everything back */
72 for (i = 0; i < buf; i++)
73 free(buffers->tbs_buffer[i].tb_buffer_data);
75 free(buffers);
76 return (0);
77 } else {
78 buffers->tbs_buffer[buf].tb_buffer_size = (write)
79 ? xfer_size : 0;
80 buffers->tbs_buffer[buf].tb_full = FALSE;
81 buffers->tbs_buffer[buf].tb_eof = FALSE;
82 buffers->tbs_buffer[buf].tb_eot = FALSE;
83 buffers->tbs_buffer[buf].tb_errno = 0;
84 buffers->tbs_buffer[buf].tb_buffer_spot = 0;
89 (void) mutex_init(&buffers->tbs_mtx, 0, NULL);
90 (void) cond_init(&buffers->tbs_in_cv, 0, NULL);
91 (void) cond_init(&buffers->tbs_out_cv, 0, NULL);
93 buffers->tbs_data_transfer_size = xfer_size;
94 buffers->tbs_ref = 1;
95 return (buffers);
99 * tlm_release_buffers
101 * give all memory back to the OS
103 void
104 tlm_release_buffers(tlm_buffers_t *buffers)
106 int i;
108 if (buffers != NULL) {
109 tlm_buffer_release_in_buf(buffers);
110 tlm_buffer_release_out_buf(buffers);
112 (void) mutex_lock(&buffers->tbs_mtx);
114 if (--buffers->tbs_ref <= 0) {
115 for (i = 0; i < TLM_TAPE_BUFFERS; i++)
116 free(buffers->tbs_buffer[i].tb_buffer_data);
120 (void) cond_destroy(&buffers->tbs_in_cv);
121 (void) cond_destroy(&buffers->tbs_out_cv);
122 (void) mutex_unlock(&buffers->tbs_mtx);
123 (void) mutex_destroy(&buffers->tbs_mtx);
124 free(buffers);
129 * tlm_buffer_mark_empty
131 * Mark a buffer empty and clear its flags. No lock is take here:
132 * the buffer should be marked empty before it is released for use
133 * by another thread.
135 void
136 tlm_buffer_mark_empty(tlm_buffer_t *buf)
138 if (buf == NULL)
139 return;
141 buf->tb_full = buf->tb_eof = buf->tb_eot = FALSE;
142 buf->tb_errno = 0;
147 * tlm_buffer_advance_in_idx
149 * Advance the input index of the buffers(round-robin) and return pointer
150 * to the next buffer in the buffer pool.
152 tlm_buffer_t *
153 tlm_buffer_advance_in_idx(tlm_buffers_t *bufs)
155 if (bufs == NULL)
156 return (NULL);
158 (void) mutex_lock(&bufs->tbs_mtx);
159 if (++bufs->tbs_buffer_in >= TLM_TAPE_BUFFERS)
160 bufs->tbs_buffer_in = 0;
162 (void) mutex_unlock(&bufs->tbs_mtx);
163 return (&bufs->tbs_buffer[bufs->tbs_buffer_in]);
168 * tlm_buffer_advance_out_idx
170 * Advance the output index of the buffers(round-robin) and return pointer
171 * to the next buffer in the buffer pool.
173 tlm_buffer_t *
174 tlm_buffer_advance_out_idx(tlm_buffers_t *bufs)
176 if (bufs == NULL)
177 return (NULL);
179 (void) mutex_lock(&bufs->tbs_mtx);
180 if (++bufs->tbs_buffer_out >= TLM_TAPE_BUFFERS)
181 bufs->tbs_buffer_out = 0;
183 (void) mutex_unlock(&bufs->tbs_mtx);
184 return (&bufs->tbs_buffer[bufs->tbs_buffer_out]);
189 * tlm_buffer_in_buf
191 * Return pointer to the next buffer in the buffer pool.
193 tlm_buffer_t *
194 tlm_buffer_in_buf(tlm_buffers_t *bufs, int *idx)
196 tlm_buffer_t *ret;
198 if (bufs == NULL)
199 return (NULL);
201 (void) mutex_lock(&bufs->tbs_mtx);
202 ret = &bufs->tbs_buffer[bufs->tbs_buffer_in];
203 if (idx)
204 *idx = bufs->tbs_buffer_in;
205 (void) mutex_unlock(&bufs->tbs_mtx);
206 return (ret);
211 * tlm_buffer_out_buf
213 * Return pointer to the next buffer in the buffer pool.
215 tlm_buffer_t *
216 tlm_buffer_out_buf(tlm_buffers_t *bufs, int *idx)
218 tlm_buffer_t *ret;
220 if (bufs == NULL)
221 return (NULL);
223 (void) mutex_lock(&bufs->tbs_mtx);
224 ret = &bufs->tbs_buffer[bufs->tbs_buffer_out];
225 if (idx)
226 *idx = bufs->tbs_buffer_out;
227 (void) mutex_unlock(&bufs->tbs_mtx);
228 return (ret);
233 * tlm_buffer_release_in_buf
235 * Another buffer is filled. Wake up the consumer if it's waiting for it.
237 void
238 tlm_buffer_release_in_buf(tlm_buffers_t *bufs)
240 (void) mutex_lock(&bufs->tbs_mtx);
241 bufs->tbs_flags |= TLM_BUF_IN_READY;
242 (void) cond_signal(&bufs->tbs_in_cv);
243 (void) mutex_unlock(&bufs->tbs_mtx);
248 * tlm_buffer_release_out_buf
250 * A buffer is used. Wake up the producer to re-fill a buffer if it's waiting
251 * for the buffer to be used.
253 void
254 tlm_buffer_release_out_buf(tlm_buffers_t *bufs)
256 (void) mutex_lock(&bufs->tbs_mtx);
257 bufs->tbs_flags |= TLM_BUF_OUT_READY;
258 (void) cond_signal(&bufs->tbs_out_cv);
259 (void) mutex_unlock(&bufs->tbs_mtx);
263 * tlm_buffer_in_buf_wait
265 * Wait for the input buffer to get available.
267 void
268 tlm_buffer_in_buf_wait(tlm_buffers_t *bufs)
271 (void) mutex_lock(&bufs->tbs_mtx);
273 while ((bufs->tbs_flags & TLM_BUF_IN_READY) == 0)
274 (void) cond_wait(&bufs->tbs_in_cv, &bufs->tbs_mtx);
276 bufs->tbs_flags &= ~TLM_BUF_IN_READY;
278 (void) mutex_unlock(&bufs->tbs_mtx);
282 * tlm_buffer_setup_timer
284 * Set up the time out value.
286 static inline void
287 tlm_buffer_setup_timer(timestruc_t *timo, unsigned milli_timo)
289 if (milli_timo == 0)
290 milli_timo = 1;
292 if (milli_timo / 1000)
293 timo->tv_sec = (milli_timo / 1000);
294 else
295 timo->tv_sec = 0;
296 timo->tv_nsec = (milli_timo % 1000) * 1000000L;
301 * tlm_buffer_in_buf_timed_wait
303 * Wait for the input buffer to get ready with a time out.
305 void
306 tlm_buffer_in_buf_timed_wait(tlm_buffers_t *bufs, unsigned int milli_timo)
309 timestruc_t timo;
311 tlm_buffer_setup_timer(&timo, milli_timo);
313 (void) mutex_lock(&bufs->tbs_mtx);
315 (void) cond_reltimedwait(&bufs->tbs_in_cv, &bufs->tbs_mtx, &timo);
318 * TLM_BUF_IN_READY doesn't matter for timedwait but clear
319 * it here so that cond_wait doesn't get the wrong result.
321 bufs->tbs_flags &= ~TLM_BUF_IN_READY;
323 (void) mutex_unlock(&bufs->tbs_mtx);
328 * tlm_buffer_out_buf_timed_wait
330 * Wait for the output buffer to get ready with a time out.
332 void
333 tlm_buffer_out_buf_timed_wait(tlm_buffers_t *bufs, unsigned int milli_timo)
335 timestruc_t timo;
337 tlm_buffer_setup_timer(&timo, milli_timo);
339 (void) mutex_lock(&bufs->tbs_mtx);
341 (void) cond_reltimedwait(&bufs->tbs_out_cv, &bufs->tbs_mtx, &timo);
344 * TLM_BUF_OUT_READY doesn't matter for timedwait but clear
345 * it here so that cond_wait doesn't get the wrong result.
347 bufs->tbs_flags &= ~TLM_BUF_OUT_READY;
349 (void) mutex_unlock(&bufs->tbs_mtx);
354 * tlm_cmd_wait
356 * TLM command synchronization typically use by command
357 * parent threads to wait for launched threads to initialize.
359 void
360 tlm_cmd_wait(tlm_cmd_t *cmd, uint32_t event_type)
362 (void) mutex_lock(&cmd->tc_mtx);
364 while ((cmd->tc_flags & event_type) == 0)
365 (void) cond_wait(&cmd->tc_cv, &cmd->tc_mtx);
367 cmd->tc_flags &= ~event_type;
368 (void) mutex_unlock(&cmd->tc_mtx);
373 * tlm_cmd_signal
375 * TLM command synchronization typically use by launched threads
376 * to unleash the parent thread.
378 void
379 tlm_cmd_signal(tlm_cmd_t *cmd, uint32_t event_type)
381 (void) mutex_lock(&cmd->tc_mtx);
383 cmd->tc_flags |= event_type;
384 (void) cond_signal(&cmd->tc_cv);
386 (void) mutex_unlock(&cmd->tc_mtx);