1 /******************************************************************************* 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 35 TRACE_TAG(INIT, 1); 36 TRACE_TAG(CMD, 1); 37 TRACE_TAG(EXEC, 1); 38 TRACE_TAG(RSP, 1); 39 TRACE_TAG(REG, 1); 40 TRACE_TAG(MEM, 1); 41 TRACE_TAG(GRAPH, 1); 42 TRACE_TAG(BUFFER, 1); 43 44 /******************************************************************************* 45 * Internal functions definitions 46 ******************************************************************************/ 47 48 /* ...execute proxy command synchronously */ 49 static 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 */ 78 static 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 */ 96 static 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 */ 113 static 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 */ 125 static 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 */ 138 static 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 */ 167 static 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 */ 192 static 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 */ 221 static 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 247 static 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 */ 313 int 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 */ 350 void 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 */ 368 int 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 */ 414 void 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 */ 447 int 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 */ 495 int 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 534 out: 535 /* ...return buffer to proxy */ 536 xf_buffer_put(b); 537 538 return r; 539 } 540 541 /* ...send a command message to component */ 542 int 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 */ 564 int 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 */ 629 void 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 */ 651 xf_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 */ 673 void 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 } 687