blob: 9487f4ea90715ab837f0f241e2e11cae11996a89 [file] [log] [blame]
Niranjan Yadlacee816e2018-04-19 12:03:47 -07001/*******************************************************************************
2* Copyright (C) 2018 Cadence Design Systems, Inc.
3*
4* Permission is hereby granted, free of charge, to any person obtaining
5* a copy of this software and associated documentation files (the
6* "Software"), to use this Software with Cadence processor cores only and
7* not with any other processors and platforms, subject to
8* the following conditions:
9*
10* The above copyright notice and this permission notice shall be included
11* in all copies or substantial portions of the Software.
12*
13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
17* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
18* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21******************************************************************************/
22
23#define MODULE_TAG PROXY
24
25/*******************************************************************************
26 * Includes
27 ******************************************************************************/
28
29#include "xf.h"
30
31/*******************************************************************************
32 * Tracing configuration
33 ******************************************************************************/
34
35TRACE_TAG(INIT, 1);
36TRACE_TAG(CMD, 1);
37TRACE_TAG(EXEC, 1);
38TRACE_TAG(RSP, 1);
39TRACE_TAG(REG, 1);
40TRACE_TAG(MEM, 1);
41TRACE_TAG(GRAPH, 1);
42TRACE_TAG(BUFFER, 1);
43
44/*******************************************************************************
45 * Internal functions definitions
46 ******************************************************************************/
47
48/* ...execute proxy command synchronously */
49static inline int xf_proxy_cmd_exec(xf_proxy_t *proxy, xf_user_msg_t *msg)
50{
51 xf_proxy_msg_t m;
52
53 /* ...send command to remote proxy */
54 m.id = msg->id, m.opcode = msg->opcode, m.length = msg->length;
55
56 /* ...translate address */
57 XF_CHK_ERR((m.address = xf_proxy_b2a(proxy, msg->buffer)) != XF_PROXY_BADADDR, -EINVAL);
58
59 /* ...pass command to remote proxy */
60 XF_CHK_API(xf_ipc_send(&proxy->ipc, &m, msg->buffer));
61
62 /* ...wait for response reception indication from proxy thread */
63 XF_CHK_API(xf_proxy_response_get(proxy, &m));
64
65 /* ...copy parameters */
66 msg->id = m.id, msg->opcode = m.opcode, msg->length = m.length;
67
68 /* ...translate address back to virtual space */
69 XF_CHK_ERR((msg->buffer = xf_proxy_a2b(proxy, m.address)) != (void *)-1, -EBADFD);
70
71 TRACE(EXEC, _b("proxy[%p]: command done: [%08x:%p:%u]"), proxy, msg->opcode, msg->buffer, msg->length);
72
73 return 0;
74}
75
76#if 0
77/* ...pass command to remote DSP */
78static inline int xf_proxy_cmd(xf_proxy_t *proxy, xf_handle_t *handle, xf_user_msg_t *m)
79{
80 xf_proxy_msg_t msg;
81
82 /* ...set session-id of the message */
83 msg.id = __XF_MSG_ID(__XF_AP_CLIENT(proxy->core, handle->client), m->id);
84 msg.opcode = m->opcode;
85 msg.length = m->length;
86
87 /* ...translate buffer pointer to shared address */
88 XF_CHK_ERR((msg.address = xf_proxy_b2a(proxy, m->buffer)) != XF_PROXY_BADADDR, -EINVAL);
89
90 /* ...submit command message to IPC layer */
91 return XF_CHK_API(xf_ipc_send(&proxy->ipc, &msg, m->buffer));
92}
93#endif /* 0 */
94
95/* ...allocate local client-id number */
96static inline u32 xf_client_alloc(xf_proxy_t *proxy, xf_handle_t *handle)
97{
98 u32 client;
99
100 if ((client = proxy->cmap[0].next) != 0)
101 {
102 /* ...pop client from free clients list */
103 proxy->cmap[0].next = proxy->cmap[client].next;
104
105 /* ...put client handle into association map */
106 handle->client = client, proxy->cmap[client].handle = handle;
107 }
108
109 return client;
110}
111
112/* ...recycle local client-id number */
113static inline void xf_client_free(xf_proxy_t *proxy, xf_handle_t *handle)
114{
115 u32 client = handle->client;
116
117 /* ...push client into head of the free clients list */
118 proxy->cmap[client].next = proxy->cmap[0].next;
119
120 /* ...adjust head of free clients */
121 proxy->cmap[0].next = client;
122}
123
124/* ...lookup client basing on its local id */
125static inline xf_handle_t * xf_client_lookup(xf_proxy_t *proxy, u32 client)
126{
127 /* ...client index must be in proper range */
128 BUG(client >= XF_CFG_PROXY_MAX_CLIENTS, _x("Invalid client index: %u"), client);
129
130 /* ...check if client index is small */
131 if (proxy->cmap[client].next < XF_CFG_PROXY_MAX_CLIENTS)
132 return NULL;
133 else
134 return proxy->cmap[client].handle;
135}
136
137/* ...create new client on remote core */
138static inline int xf_client_register(xf_proxy_t *proxy, xf_handle_t *handle, xf_id_t id, u32 core)
139{
140 void *b = xf_handle_aux(handle);
141 xf_user_msg_t msg;
142
143 /* ...set session-id: source is local proxy, destination is remote proxy */
144 msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_DSP_PROXY(core));
145 msg.opcode = XF_REGISTER;
146 msg.buffer = b;
147 msg.length = strlen(id) + 1;
148
149 /* ...copy component identifier */
150 strncpy(b, id, xf_buffer_length(handle->aux));
151
152 /* ...execute command synchronously */
153 XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
154
155 /* ...check operation is successfull */
156 XF_CHK_ERR(msg.opcode == (u32) XF_REGISTER, -EFAULT);
157
158 /* ...save received component global client-id */
159 handle->id = XF_MSG_SRC(msg.id);
160
161 TRACE(REG, _b("[%p]=[%s:%u:%u]"), handle, id, XF_PORT_CORE(handle->id), XF_PORT_CLIENT(handle->id));
162
163 return 0;
164}
165
166/* ...unregister client from remote proxy */
167static inline int xf_client_unregister(xf_proxy_t *proxy, xf_handle_t *handle)
168{
169 xf_user_msg_t msg;
170
171 /* ...make sure the client is consistent */
172 BUG(proxy->cmap[handle->client].handle != handle, _x("Invalid handle: %p"), handle);
173
174 /* ...set message parameters */
175 msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), handle->id);
176 msg.opcode = XF_UNREGISTER;
177 msg.buffer = NULL;
178 msg.length = 0;
179
180 /* ...synchronously execute command on remote proxy */
181 XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
182
183 /* ...opcode must be XF_UNREGISTER - tbd */
184 BUG(msg.opcode != XF_UNREGISTER, _x("Invalid opcode: %X"), msg.opcode);
185
186 TRACE(REG, _b("%p[%u:%u] unregistered"), handle, XF_PORT_CORE(handle->id), XF_PORT_CLIENT(handle->id));
187
188 return 0;
189}
190
191/* ...allocate shared buffer */
192static inline int xf_proxy_buffer_alloc(xf_proxy_t *proxy, u32 length, void **buffer)
193{
194 u32 core = proxy->core;
195 xf_user_msg_t msg;
196
197 /* ...prepare command parameters */
198 msg.id = __XF_MSG_ID(__XF_AP_PROXY(core), __XF_DSP_PROXY(core));
199 msg.opcode = XF_ALLOC;
200 msg.length = length;
201 msg.buffer = NULL;
202
203 /* ...synchronously execute command on remote proxy */
204 XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
205
206 /* ...check if response is valid */
207 XF_CHK_ERR(msg.opcode == XF_ALLOC, -EBADFD);
208
209 /* ...check if allocation is successful */
210 XF_CHK_ERR(msg.buffer != NULL, -ENOMEM);
211
212 /* ...save output parameter */
213 *buffer = msg.buffer;
214
215 TRACE(MEM, _b("proxy-%u: allocated [%p:%u]"), core, *buffer, length);
216
217 return 0;
218}
219
220/* ...free shared AP-DSP memory */
221static inline int xf_proxy_buffer_free(xf_proxy_t *proxy, void *buffer, u32 length)
222{
223 u32 core = proxy->core;
224 xf_user_msg_t msg;
225
226 /* ...prepare command parameters */
227 msg.id = __XF_MSG_ID(__XF_AP_PROXY(core), __XF_DSP_PROXY(core));
228 msg.opcode = XF_FREE;
229 msg.length = length;
230 msg.buffer = buffer;
231
232 /* ...synchronously execute command on remote proxy */
233 XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
234
235 /* ...check if response is valid */
236 XF_CHK_ERR(msg.opcode == XF_FREE, -EBADFD);
237
238 TRACE(MEM, _b("proxy-%u: free [%p:%u]"), core, buffer, length);
239
240 return 0;
241}
242
243/*******************************************************************************
244 * Proxy interface asynchronous receiving thread
245 ******************************************************************************/
246
247static void * xf_proxy_thread(void *arg)
248{
249 xf_proxy_t *proxy = arg;
250 xf_handle_t *client;
251 int r;
252
253 /* ...start polling thread */
254 while (1)
255 {
256 xf_proxy_msg_t m;
257 xf_user_msg_t msg;
258
259 /* ...wait for response from remote proxy (infinite timeout) */
260 if ((r = xf_ipc_wait(&proxy->ipc, 0)) < 0)
261 break;
262
263 /* ...retrieve all responses received */
264 while ((r = xf_ipc_recv(&proxy->ipc, &m, &msg.buffer)) == sizeof(m))
265 {
266 /* ...make sure we have proper core identifier of SHMEM interface */
267 BUG(XF_MSG_DST_CORE(m.id) != proxy->core, _x("Invalid session-id: %X (core=%u)"), m.id, proxy->core);
268
269 /* ...make sure translation is successful */
270 BUG(msg.buffer == (void *)-1, _x("Invalid buffer address: %08x"), m.address);
271
272 /* ...retrieve information fields */
273 msg.id = XF_MSG_SRC(m.id), msg.opcode = m.opcode, msg.length = m.length;
274
275 TRACE(RSP, _b("R[%08x]:(%08x,%u,%08x)"), m.id, m.opcode, m.length, m.address);
276
277 /* ...lookup component basing on destination port specification */
278 if (XF_AP_CLIENT(m.id) == 0)
279 {
280 /* ...put proxy response to local IPC queue */
281 xf_proxy_response_put(proxy, &m);
282 }
283 else if ((client = xf_client_lookup(proxy, XF_AP_CLIENT(m.id))) != NULL)
284 {
285 /* ...client is found; invoke its response callback (must be non-blocking) */
286 client->response(client, &msg);
287 }
288 else
289 {
290 /* ...client has been disconnected already; drop message */
291 TRACE(RSP, _b("Client look-up failed - drop message"));
292 }
293 }
294
295 /* ...if result code is negative; terminate thread operation */
296 if (r < 0)
297 {
298 TRACE(ERROR, _x("abnormal proxy[%p] thread termination: %d"), proxy, r);
299 break;
300 }
301 }
302
303 TRACE(INIT, _b("IPC proxy[%p] thread terminated: %d"), proxy, r);
304
305 return (void *)(intptr_t)r;
306}
307
308/*******************************************************************************
309 * HiFi proxy API
310 ******************************************************************************/
311
312/* ...open HiFi proxy */
313int xf_proxy_init(xf_proxy_t *proxy, u32 core, void *p_shmem)
314{
315 u32 i;
316 int r;
317
318 /* ...initialize proxy lock */
319 __xf_lock_init(&proxy->lock);
320
321 /* ...open proxy IPC interface */
322 XF_CHK_API(xf_ipc_open(&proxy->ipc, core, p_shmem));
323
324 /* ...save proxy core - hmm, too much core identifiers - tbd */
325 proxy->core = core;
326
327 /* ...line-up all clients into single-linked list */
328 for (i = 0; i < XF_CFG_PROXY_MAX_CLIENTS - 1; i++)
329 {
330 proxy->cmap[i].next = i + 1;
331 }
332
333 /* ...tail of the list points back to head (list terminator) */
334 proxy->cmap[i].next = 0;
335
336 /* ...initialize thread attributes (joinable, with minimal stack) */
337 if ((r = __xf_thread_create(&proxy->thread, xf_proxy_thread, proxy)) < 0)
338 {
339 TRACE(ERROR, _x("Failed to create polling thread: %d"), r);
340 xf_ipc_close(&proxy->ipc, core);
341 return r;
342 }
343
344 TRACE(INIT, _b("proxy-%u[%p] opened"), core, proxy);
345
346 return 0;
347}
348
349/* ...close proxy handle */
350void xf_proxy_close(xf_proxy_t *proxy)
351{
352 u32 core = proxy->core;
353
354 /* ...terminate proxy thread */
355 __xf_thread_destroy(&proxy->thread);
356
357 /* ...close proxy IPC interface */
358 xf_ipc_close(&proxy->ipc, core);
359
360 TRACE(INIT, _b("proxy-%u[%p] closed"), core, proxy);
361}
362
363/*******************************************************************************
364 * HiFi component API
365 ******************************************************************************/
366
367/* ...open component handle */
368int xf_open(xf_proxy_t *proxy, xf_handle_t *handle, xf_id_t id, u32 core, xf_response_cb response)
369{
370 int r;
371
372 /* ...retrieve auxiliary control buffer from proxy - need I */
373 XF_CHK_ERR(handle->aux = xf_buffer_get(proxy->aux), -EBUSY);
374
375 /* ...initialize IPC data */
376 XF_CHK_API(xf_ipc_data_init(&handle->ipc));
377
378 /* ...register client in interlocked fashion */
379 xf_proxy_lock(proxy);
380
381 /* ...allocate local client */
382 if (xf_client_alloc(proxy, handle) == 0)
383 {
384 TRACE(ERROR, _x("client allocation failed"));
385 r = -EBUSY;
386 }
387 else if ((r = xf_client_register(proxy, handle, id, core)) < 0)
388 {
389 TRACE(ERROR, _x("client registering failed"));
390 xf_client_free(proxy, handle);
391 }
392
393 xf_proxy_unlock(proxy);
394
395 /* ...if failed, release buffer handle */
396 if (r < 0)
397 {
398 /* ...operation failed; return buffer back to proxy pool */
399 xf_buffer_put(handle->aux), handle->aux = NULL;
400 }
401 else
402 {
403 /* ...operation completed successfully; assign handle data */
404 handle->response = response;
405 handle->proxy = proxy;
406
407 TRACE(INIT, _b("component[%p]:(id=%s,core=%u) created"), handle, id, core);
408 }
409
410 return XF_CHK_API(r);
411}
412
413/* ...close component handle */
414void xf_close(xf_handle_t *handle)
415{
416 xf_proxy_t *proxy = handle->proxy;
417
418 /* ...do I need to take component lock here? guess no - tbd */
419
420 /* ...buffers and stuff? - tbd */
421
422 /* ...acquire global proxy lock */
423 xf_proxy_lock(proxy);
424
425 /* ...unregister component from remote DSP proxy (ignore result code) */
426 (void) xf_client_unregister(proxy, handle);
427
428 /* ...recycle client-id afterwards */
429 xf_client_free(proxy, handle);
430
431 /* ...release global proxy lock */
432 xf_proxy_unlock(proxy);
433
434 /* ...destroy IPC data */
435 xf_ipc_data_destroy(&handle->ipc);
436
437 /* ...clear handle data */
438 xf_buffer_put(handle->aux), handle->aux = NULL;
439
440 /* ...wipe out proxy pointer */
441 handle->proxy = NULL;
442
443 TRACE(INIT, _b("component[%p] destroyed"), handle);
444}
445
446/* ...port binding function */
447int xf_route(xf_handle_t *src, u32 src_port, xf_handle_t *dst, u32 dst_port, u32 num, u32 size, u32 align)
448{
449 xf_proxy_t *proxy = src->proxy;
450 xf_buffer_t *b;
451 xf_route_port_msg_t *m;
452 xf_user_msg_t msg;
453
454 /* ...sanity checks - proxy pointers are same */
455 XF_CHK_ERR(proxy == dst->proxy, -EINVAL);
456
457 /* ...buffer data is sane */
458 XF_CHK_ERR(num && size && xf_is_power_of_two(align), -EINVAL);
459
460 /* ...get control buffer */
461 XF_CHK_ERR(b = xf_buffer_get(proxy->aux), -EBUSY);
462
463 /* ...get message buffer */
464 m = xf_buffer_data(b);
465
466 /* ...fill-in message parameters */
467 //m->src = __XF_PORT_SPEC2(src->id, src_port);
468 m->dst = __XF_PORT_SPEC2(dst->id, dst_port);
469 m->alloc_number = num;
470 m->alloc_size = size;
471 m->alloc_align = align;
472
473 /* ...set command parameters */
474 msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_PORT_SPEC2(src->id, src_port));
475 msg.opcode = XF_ROUTE;
476 msg.length = sizeof(*m);
477 msg.buffer = m;
478
479 /* ...synchronously execute command on remote DSP */
480 XF_CHK_API(xf_proxy_cmd_exec(proxy, &msg));
481
482 /* ...return buffer to proxy */
483 xf_buffer_put(b);
484
485 /* ...check result is successfull */
486 XF_CHK_ERR(msg.opcode == (u32) XF_ROUTE, -ENOMEM);
487
488 /* ...port binding completed */
489 TRACE(GRAPH, _b("[%p]:%u bound to [%p]:%u"), src, src_port, dst, dst_port);
490
491 return 0;
492}
493
494/* ...port unbinding function */
495int xf_unroute(xf_handle_t *src, u32 src_port)
496{
497 xf_proxy_t *proxy = src->proxy;
498 xf_buffer_t *b;
499 xf_unroute_port_msg_t *m;
500 xf_user_msg_t msg;
501 int r;
502
503 /* ...get control buffer */
504 XF_CHK_ERR(b = xf_buffer_get(proxy->aux), -EBUSY);
505
506 /* ...get message buffer */
507 m = xf_buffer_data(b);
508
509 /* ...fill-in message parameters */
510 //m->src = __XF_PORT_SPEC2(src->id, src_port);
511
512 /* ...set command parameters */
513 msg.id = __XF_MSG_ID(__XF_AP_PROXY(proxy->core), __XF_PORT_SPEC2(src->id, src_port));
514 msg.opcode = XF_UNROUTE;
515 msg.length = sizeof(*m);
516 msg.buffer = m;
517
518 /* ...synchronously execute command on remote DSP */
519 if ((r = xf_proxy_cmd_exec(proxy, &msg)) != 0)
520 {
521 TRACE(ERROR, _x("Command failed: %d"), r);
522 goto out;
523 }
524 else if (msg.opcode != (u32) XF_UNROUTE)
525 {
526 TRACE(ERROR, _x("Port unbinding failed"));
527 r = -EBADFD;
528 goto out;
529 }
530
531 /* ...port binding completed */
532 TRACE(GRAPH, _b("[%p]:%u unbound"), src, src_port);
533
534out:
535 /* ...return buffer to proxy */
536 xf_buffer_put(b);
537
538 return r;
539}
540
541/* ...send a command message to component */
542int xf_command(xf_handle_t *handle, u32 port, u32 opcode, void *buffer, u32 length)
543{
544 xf_proxy_t *proxy = handle->proxy;
545 xf_proxy_msg_t msg;
546
547 /* ...fill-in message parameters */
548 msg.id = __XF_MSG_ID(__XF_AP_CLIENT(proxy->core, handle->client), __XF_PORT_SPEC2(handle->id, port));
549 msg.opcode = opcode;
550 msg.length = length;
551 XF_CHK_ERR((msg.address = xf_proxy_b2a(proxy, buffer)) != XF_PROXY_BADADDR, -EINVAL);
552
553 TRACE(CMD, _b("[%p]:[%08x]:(%08x,%u,%p)"), handle, msg.id, opcode, length, buffer);
554
555 /* ...pass command to IPC layer */
556 return XF_CHK_API(xf_ipc_send(&proxy->ipc, &msg, buffer));
557}
558
559/*******************************************************************************
560 * Buffer pool API
561 ******************************************************************************/
562
563/* ...allocate buffer pool */
564int xf_pool_alloc(xf_proxy_t *proxy, u32 number, u32 length, xf_pool_type_t type, xf_pool_t **pool, s32 id,
565 xaf_mem_malloc_fxn_t xaf_malloc, xaf_mem_free_fxn_t xaf_free)
566{
567 xf_pool_t *p;
568 xf_buffer_t *b;
569 void *data;
570 int r;
571
572 /* ...unused arg */
573 (void) type;
574
575 /* ...basic sanity checks; number of buffers is positive */
576 XF_CHK_ERR(number > 0, -EINVAL);
577
578 /* ...get properly aligned buffer length */
579 length = (length + XF_PROXY_ALIGNMENT - 1) & ~(XF_PROXY_ALIGNMENT - 1);
580
581 /* ...allocate data structure */
582 p = xaf_malloc(offset_of(xf_pool_t, buffer) + number * sizeof(xf_buffer_t), id);
583 XF_CHK_ERR(p, -ENOMEM);
584
585 /* ...issue memory pool allocation request to remote DSP */
586 xf_proxy_lock(proxy);
587 r = xf_proxy_buffer_alloc(proxy, number * length, &p->p);
588 xf_proxy_unlock(proxy);
589
590 /* ...if operation is failed, do cleanup */
591 if (r < 0)
592 {
593 TRACE(ERROR, _x("failed to allocate buffer: %d"), r);
594 xaf_free(p, id);
595 return r;
596 }
597 else
598 {
599 /* ...set pool parameters */
600 p->number = number, p->length = length;
601 p->proxy = proxy;
602 }
603
604 /* ...create individual buffers and link them into free list */
605 for (p->free = b = &p->buffer[0], data = p->p; number > 0; number--, b++)
606 {
607 /* ...set address of the buffer (no length there) */
608 b->address = data;
609
610 /* ...file buffer into the free list */
611 b->link.next = b + 1;
612
613 /* ...advance data pointer in contiguous buffer */
614 data = (unsigned char *) data + length;
615 }
616
617 /* ...terminate list of buffers (not too good - tbd) */
618 b[-1].link.next = NULL;
619
620 TRACE(BUFFER, _b("[%p]: pool[%p] created: %u * %u"), proxy, p, p->number, p->length);
621
622 /* ...return buffer pointer */
623 *pool = p;
624
625 return 0;
626}
627
628/* ...buffer pool destruction */
629void xf_pool_free(xf_pool_t *pool, s32 id, xaf_mem_free_fxn_t xaf_free)
630{
631 xf_proxy_t *proxy = pool->proxy;
632
633 /* ...check buffers are all freed - tbd */
634
635 /* ...use global proxy lock for pool operations protection */
636 xf_proxy_lock(proxy);
637
638 /* ...release allocated buffer on remote DSP */
639 xf_proxy_buffer_free(proxy, pool->p, pool->length * pool->number);
640
641 /* ...release global proxy lock */
642 xf_proxy_unlock(proxy);
643
644 /* ...deallocate pool structure itself */
645 xaf_free(pool, id);
646
647 TRACE(BUFFER, _b("[%p]::pool[%p] destroyed"), proxy, pool);
648}
649
650/* ...get new buffer from a pool */
651xf_buffer_t * xf_buffer_get(xf_pool_t *pool)
652{
653 xf_buffer_t *b;
654
655 /* ...use global proxy lock for pool operations protection */
656 xf_proxy_lock(pool->proxy);
657
658 /* ...take buffer from a head of the free list */
659 if ((b = pool->free) != NULL)
660 {
661 /* ...advance free list head */
662 pool->free = b->link.next, b->link.pool = pool;
663
664 TRACE(BUFFER, _b("pool[%p]::get[%p]"), pool, b);
665 }
666
667 xf_proxy_unlock(pool->proxy);
668
669 return b;
670}
671
672/* ...return buffer back to pool */
673void xf_buffer_put(xf_buffer_t *buffer)
674{
675 xf_pool_t *pool = buffer->link.pool;
676
677 /* ...use global proxy lock for pool operations protection */
678 xf_proxy_lock(pool->proxy);
679
680 /* ...put buffer back to a pool */
681 buffer->link.next = pool->free, pool->free = buffer;
682
683 TRACE(BUFFER, _b("pool[%p]::put[%p]"), pool, buffer);
684
685 xf_proxy_unlock(pool->proxy);
686}