1 /**************************************************************************
5 Copyright 2012 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 #include "tbm_bufmgr.h"
35 #include "tbm_bufmgr_int.h"
36 #include "tbm_bufmgr_backend.h"
54 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
55 static pthread_mutex_t tbm_bufmgr_lock = PTHREAD_MUTEX_INITIALIZER;
56 static __thread tbm_error_e tbm_last_error = TBM_ERROR_NONE;
58 static void _tbm_bufmgr_mutex_unlock(void);
60 //#define TBM_BUFMGR_INIT_TIME
62 #define PREFIX_LIB "libtbm_"
63 #define SUFFIX_LIB ".so"
64 #define DEFAULT_LIB PREFIX_LIB"default"SUFFIX_LIB
66 /* values to indicate unspecified fields in XF86ModReqInfo. */
67 #define MAJOR_UNSPEC 0xFF
68 #define MINOR_UNSPEC 0xFF
69 #define PATCH_UNSPEC 0xFFFF
70 #define ABI_VERS_UNSPEC 0xFFFFFFFF
72 #define MODULE_VERSION_NUMERIC(maj, min, patch) \
73 ((((maj) & 0xFF) << 24) | (((min) & 0xFF) << 16) | (patch & 0xFFFF))
74 #define GET_MODULE_MAJOR_VERSION(vers) (((vers) >> 24) & 0xFF)
75 #define GET_MODULE_MINOR_VERSION(vers) (((vers) >> 16) & 0xFF)
76 #define GET_MODULE_PATCHLEVEL(vers) ((vers) & 0xFFFF)
79 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
81 TBM_LOG_E("'%s' failed.\n", #cond);\
82 _tbm_bufmgr_mutex_unlock();\
87 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
89 TBM_LOG_E("'%s' failed.\n", #cond);\
90 _tbm_bufmgr_mutex_unlock();\
102 _tbm_set_last_result(tbm_error_e err)
104 tbm_last_error = err;
108 _tbm_bufmgr_mutex_init(void)
110 static bool tbm_bufmgr_mutex_init = false;
112 if (tbm_bufmgr_mutex_init)
115 if (pthread_mutex_init(&tbm_bufmgr_lock, NULL)) {
116 TBM_LOG_E("fail: Cannot pthread_mutex_init for tbm_bufmgr_lock.\n");
120 tbm_bufmgr_mutex_init = true;
126 _tbm_bufmgr_mutex_lock(void)
128 if (!_tbm_bufmgr_mutex_init()) {
129 TBM_LOG_E("fail: _tbm_bufmgr_mutex_init()\n");
133 pthread_mutex_lock(&tbm_bufmgr_lock);
137 _tbm_bufmgr_mutex_unlock(void)
139 pthread_mutex_unlock(&tbm_bufmgr_lock);
143 _tbm_flag_to_str(int f)
145 static char str[255];
147 if (f == TBM_BO_DEFAULT)
148 snprintf(str, 255, "DEFAULT");
152 if (f & TBM_BO_SCANOUT)
153 c = snprintf(&str[c], 255, "SCANOUT");
155 if (f & TBM_BO_NONCACHABLE) {
157 c = snprintf(&str[c], 255, ", ");
158 c = snprintf(&str[c], 255, "NONCACHABLE,");
163 c = snprintf(&str[c], 255, ", ");
164 c = snprintf(&str[c], 255, "WC");
171 /* LCOV_EXCL_START */
173 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
175 static int last_chk_bo_cnt = 0;
177 if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
178 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
179 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n",
182 tbm_bufmgr_debug_show(bufmgr);
184 last_chk_bo_cnt = bufmgr->bo_cnt;
189 _tbm_util_get_max_surface_size(int *w, int *h)
191 tbm_surface_info_s info;
192 tbm_surface_h surface = NULL;
198 if (gBufMgr == NULL || LIST_IS_EMPTY(&gBufMgr->surf_list))
201 LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link) {
202 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
206 if (*h < info.height)
215 _tbm_util_get_appname_brief(char *brief)
219 char temp[255] = {0,};
220 char *saveptr = NULL;
222 token = strtok_r(brief, delim, &saveptr);
224 while (token != NULL) {
225 memset(temp, 0x00, 255 * sizeof(char));
226 strncpy(temp, token, 254 * sizeof(char));
227 token = strtok_r(NULL, delim, &saveptr);
230 snprintf(brief, sizeof(temp), "%s", temp);
234 _tbm_util_get_appname_from_pid(long pid, char *str)
236 char fn_cmdline[255] = {0, }, cmdline[255];
240 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", pid);
242 fp = fopen(fn_cmdline, "r");
244 TBM_LOG_E("cannot file open %s\n", fn_cmdline);
248 if (!fgets(cmdline, 255, fp)) {
249 TBM_LOG_E("fail to get appname for pid(%ld)\n", pid);
256 len = strlen(cmdline);
258 memset(cmdline, 0x00, 255);
262 snprintf(str, sizeof(cmdline), "%s", cmdline);
267 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
269 tbm_user_data *old_data = NULL;
271 if (LIST_IS_EMPTY(user_data_list))
274 LIST_FOR_EACH_ENTRY(old_data, user_data_list, item_link) {
275 if (old_data->key == key)
283 *user_data_create(unsigned long key, tbm_data_free data_free_func)
285 tbm_user_data *user_data;
287 user_data = calloc(1, sizeof(tbm_user_data));
289 TBM_LOG_E("fail to allocate an user_date\n");
293 user_data->key = key;
294 user_data->free_func = data_free_func;
300 user_data_delete(tbm_user_data *user_data)
302 if (user_data->data && user_data->free_func)
303 user_data->free_func(user_data->data);
305 LIST_DEL(&user_data->item_link);
311 _bo_lock(tbm_bo bo, int device, int opt)
313 tbm_bufmgr bufmgr = bo->bufmgr;
316 if (bufmgr->backend->bo_lock)
317 ret = bufmgr->backend->bo_lock(bo, device, opt);
323 _bo_unlock(tbm_bo bo)
325 tbm_bufmgr bufmgr = bo->bufmgr;
327 if (bufmgr->backend->bo_unlock)
328 bufmgr->backend->bo_unlock(bo);
332 _tbm_bo_lock(tbm_bo bo, int device, int opt)
342 /* do not try to lock the bo */
343 if (bufmgr->lock_type == LOCK_TRY_NEVER)
346 if (bo->lock_cnt < 0) {
347 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
354 switch (bufmgr->lock_type) {
356 if (bo->lock_cnt == 0) {
357 _tbm_bufmgr_mutex_unlock();
358 ret = _bo_lock(bo, device, opt);
359 _tbm_bufmgr_mutex_lock();
365 case LOCK_TRY_ALWAYS:
366 _tbm_bufmgr_mutex_unlock();
367 ret = _bo_lock(bo, device, opt);
368 _tbm_bufmgr_mutex_lock();
373 TBM_LOG_E("error bo:%p lock_type[%d] is wrong.\n",
374 bo, bufmgr->lock_type);
379 TBM_DBG_LOCK(">> LOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
385 _tbm_bo_unlock(tbm_bo bo)
395 /* do not try to unlock the bo */
396 if (bufmgr->lock_type == LOCK_TRY_NEVER)
401 switch (bufmgr->lock_type) {
403 if (bo->lock_cnt > 0) {
405 if (bo->lock_cnt == 0)
409 case LOCK_TRY_ALWAYS:
410 if (bo->lock_cnt > 0) {
416 TBM_LOG_E("error bo:%p lock_type[%d] is wrong.\n",
417 bo, bufmgr->lock_type);
421 if (bo->lock_cnt < 0)
424 TBM_DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n", bo, old, bo->lock_cnt);
428 _tbm_bo_is_valid(tbm_bo bo)
430 tbm_bo old_data = NULL;
432 if (bo == NULL || gBufMgr == NULL) {
433 TBM_LOG_E("error: bo is NULL or tbm_bufmgr was deinited\n");
437 if (LIST_IS_EMPTY(&gBufMgr->bo_list)) {
438 TBM_LOG_E("error: gBufMgr->bo_list is EMPTY.\n");
442 LIST_FOR_EACH_ENTRY(old_data, &gBufMgr->bo_list, item_link) {
447 TBM_LOG_E("error: No valid bo(%p).\n", bo);
452 /* LCOV_EXCL_START */
454 _check_version(TBMModuleVersionInfo *data)
459 abimaj = GET_ABI_MAJOR(data->abiversion);
460 abimin = GET_ABI_MINOR(data->abiversion);
462 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
463 data->modname ? data->modname : "UNKNOWN!",
464 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
466 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
467 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
469 TBM_DBG("TBM ABI version %d.%d\n",
472 if (abimaj != vermaj) {
473 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
476 } else if (abimin > vermin) {
477 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
486 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
488 char path[PATH_MAX] = {0, };
489 TBMModuleVersionInfo *vers;
490 TBMModuleData *initdata;
494 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
496 module_data = dlopen(path, RTLD_LAZY);
498 TBM_LOG_E("failed to load module: %s(%s)\n", dlerror(), file);
502 initdata = dlsym(module_data, "tbmModuleData");
504 TBM_LOG_E("Error: module does not have data object.\n");
508 vers = initdata->vers;
510 TBM_LOG_E("Error: module does not supply version information.\n");
514 init = initdata->init;
516 TBM_LOG_E("Error: module does not supply init symbol.\n");
520 if (!_check_version(vers)) {
521 TBM_LOG_E("Fail to check version.\n");
525 if (!init(bufmgr, fd)) {
526 TBM_LOG_E("Fail to init module(%s)\n", file);
530 if (!bufmgr->backend || !bufmgr->backend->priv) {
531 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n", file);
535 bufmgr->module_data = module_data;
537 TBM_DBG("Success to load module(%s)\n", file);
542 dlclose(module_data);
547 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
549 struct dirent **namelist;
552 /* load bufmgr priv from default lib */
553 if (_tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB))
556 /* load bufmgr priv from configured path */
557 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
559 TBM_LOG_E("no files : %s\n", BUFMGR_MODULE_DIR);
564 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
565 const char *p = strstr(namelist[n]->d_name, SUFFIX_LIB);
567 if (p && !strcmp(p, SUFFIX_LIB))
568 ret = _tbm_bufmgr_load_module(bufmgr, fd,
569 namelist[n]->d_name);
582 tbm_bufmgr_init(int fd)
584 #ifdef TBM_BUFMGR_INIT_TIME
585 struct timeval start_tv, end_tv;
589 #ifdef TBM_BUFMGR_INIT_TIME
590 /* get the start tv */
591 gettimeofday(&start_tv, NULL);
594 /* LCOV_EXCL_START */
596 env = getenv("TBM_DLOG");
599 TBM_LOG_D("TBM_DLOG=%s\n", env);
605 env = getenv("TBM_DEBUG");
608 TBM_LOG_D("TBM_DEBUG=%s\n", env);
614 env = getenv("TBM_TRACE");
617 TBM_LOG_D("TBM_TRACE=%s\n", env);
623 pthread_mutex_lock(&gLock);
626 TBM_LOG_W("!!!!!WARNING:: The tbm_bufmgr_init DOSE NOT use argument fd ANYMORE.\n");
627 TBM_LOG_W("!!!!!WARNING:: IT WILL BE CHANGED like tbm_bufmgr_init(int fd) --> tbm_bufmgr_init(void).\n");
630 /* initialize buffer manager */
632 gBufMgr->ref_count++;
633 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
634 pthread_mutex_unlock(&gLock);
638 TBM_DBG("bufmgr init\n");
640 /* allocate bufmgr */
641 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
643 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
644 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
645 pthread_mutex_unlock(&gLock);
651 /* load bufmgr priv from env */
652 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
653 /* LCOV_EXCL_START */
654 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
655 TBM_LOG_E("error : Fail to load bufmgr backend\n");
658 pthread_mutex_unlock(&gLock);
663 /* log for tbm backend_flag */
664 TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
667 gBufMgr->ref_count = 1;
669 TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
670 gBufMgr, gBufMgr->ref_count);
672 /* setup the lock_type */
673 env = getenv("BUFMGR_LOCK_TYPE");
674 if (env && !strcmp(env, "always"))
675 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
676 else if (env && !strcmp(env, "none"))
677 gBufMgr->lock_type = LOCK_TRY_NEVER;
678 else if (env && !strcmp(env, "once"))
679 gBufMgr->lock_type = LOCK_TRY_ONCE;
681 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
683 TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", env ? env : "default:once");
685 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
687 /* intialize bo_list */
688 LIST_INITHEAD(&gBufMgr->bo_list);
690 /* intialize surf_list */
691 LIST_INITHEAD(&gBufMgr->surf_list);
693 /* intialize surf_queue_list */
694 LIST_INITHEAD(&gBufMgr->surf_queue_list);
696 /* intialize debug_key_list */
697 LIST_INITHEAD(&gBufMgr->debug_key_list);
699 #ifdef TBM_BUFMGR_INIT_TIME
701 gettimeofday(&end_tv, NULL);
702 TBM_LOG_I("tbm_bufmgr_init time: %ld ms", ((end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000) - (start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000)));
705 pthread_mutex_unlock(&gLock);
711 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
713 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
715 pthread_mutex_lock(&gLock);
718 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
719 pthread_mutex_unlock(&gLock);
724 if (bufmgr->ref_count > 0) {
725 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
726 pthread_mutex_unlock(&gLock);
730 /* destroy bo_list */
731 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
732 tbm_bo bo = NULL, tmp;
734 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
735 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
741 /* destroy surf_list */
742 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
743 tbm_surface_h surf = NULL, tmp;
745 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
746 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
747 tbm_surface_destroy(surf);
751 /* destroy bufmgr priv */
752 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
753 bufmgr->backend->priv = NULL;
754 tbm_backend_free(bufmgr->backend);
755 bufmgr->backend = NULL;
757 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
759 dlclose(bufmgr->module_data);
767 pthread_mutex_unlock(&gLock);
771 tbm_bo_size(tbm_bo bo)
773 tbm_bufmgr bufmgr = gBufMgr;
776 _tbm_bufmgr_mutex_lock();
778 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
779 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
781 size = bufmgr->backend->bo_size(bo);
783 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
785 _tbm_bufmgr_mutex_unlock();
791 tbm_bo_ref(tbm_bo bo)
793 _tbm_bufmgr_mutex_lock();
795 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
796 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
800 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
802 _tbm_bufmgr_mutex_unlock();
808 tbm_bo_unref(tbm_bo bo)
810 tbm_bufmgr bufmgr = gBufMgr;
812 _tbm_bufmgr_mutex_lock();
814 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
815 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
817 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
819 if (bo->ref_cnt <= 0) {
820 _tbm_bufmgr_mutex_unlock();
825 if (bo->ref_cnt == 0) {
826 /* destory the user_data_list */
827 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
828 tbm_user_data *old_data = NULL, *tmp;
830 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp,
831 &bo->user_data_list, item_link) {
832 TBM_DBG("free user_data\n");
833 user_data_delete(old_data);
837 while (bo->lock_cnt > 0) {
838 TBM_LOG_E("error lock_cnt:%d\n", bo->lock_cnt);
843 /* call the bo_free */
844 bufmgr->backend->bo_free(bo);
847 LIST_DEL(&bo->item_link);
853 _tbm_bufmgr_mutex_unlock();
857 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
862 _tbm_bufmgr_mutex_lock();
864 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
865 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
866 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
868 bo = calloc(1, sizeof(struct _tbm_bo));
870 TBM_LOG_E("error: fail to create of tbm_bo size(%d) flag(%s)\n",
871 size, _tbm_flag_to_str(flags));
872 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
873 _tbm_bufmgr_mutex_unlock();
877 _tbm_util_check_bo_cnt(bufmgr);
881 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
883 TBM_LOG_E("error: fail to create of tbm_bo size(%d) flag(%s)\n",
884 size, _tbm_flag_to_str(flags));
885 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
887 _tbm_bufmgr_mutex_unlock();
897 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt,
898 _tbm_flag_to_str(bo->flags));
900 LIST_INITHEAD(&bo->user_data_list);
902 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
904 _tbm_bufmgr_mutex_unlock();
910 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
915 _tbm_bufmgr_mutex_lock();
917 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
918 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
920 if (!bufmgr->backend->bo_import) {
921 _tbm_bufmgr_mutex_unlock();
925 _tbm_util_check_bo_cnt(bufmgr);
927 bo = calloc(1, sizeof(struct _tbm_bo));
929 TBM_LOG_E("error: fail to import of tbm_bo by key(%d)\n", key);
930 _tbm_bufmgr_mutex_unlock();
936 bo_priv = bufmgr->backend->bo_import(bo, key);
938 TBM_LOG_E("error: fail to import of tbm_bo by key(%d)\n", key);
939 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
941 _tbm_bufmgr_mutex_unlock();
945 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
948 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
949 if (bo2->priv == bo_priv) {
950 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
951 bo2, bo2->ref_cnt, key,
952 _tbm_flag_to_str(bo2->flags));
955 _tbm_bufmgr_mutex_unlock();
966 if (bufmgr->backend->bo_get_flags)
967 bo->flags = bufmgr->backend->bo_get_flags(bo);
969 bo->flags = TBM_BO_DEFAULT;
971 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
972 bo, bo->ref_cnt, key, _tbm_flag_to_str(bo->flags));
974 LIST_INITHEAD(&bo->user_data_list);
976 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
978 _tbm_bufmgr_mutex_unlock();
984 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
989 _tbm_bufmgr_mutex_lock();
991 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
992 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
994 if (!bufmgr->backend->bo_import_fd) {
995 _tbm_bufmgr_mutex_unlock();
999 _tbm_util_check_bo_cnt(bufmgr);
1001 bo = calloc(1, sizeof(struct _tbm_bo));
1003 TBM_LOG_E("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1004 _tbm_bufmgr_mutex_unlock();
1008 bo->bufmgr = bufmgr;
1010 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1012 TBM_LOG_E("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1013 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1015 _tbm_bufmgr_mutex_unlock();
1019 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1022 LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
1023 if (bo2->priv == bo_priv) {
1024 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1025 bo2, bo2->ref_cnt, fd,
1026 _tbm_flag_to_str(bo2->flags));
1029 _tbm_bufmgr_mutex_unlock();
1040 if (bufmgr->backend->bo_get_flags)
1041 bo->flags = bufmgr->backend->bo_get_flags(bo);
1043 bo->flags = TBM_BO_DEFAULT;
1045 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1046 bo, bo->ref_cnt, fd, _tbm_flag_to_str(bo->flags));
1048 LIST_INITHEAD(&bo->user_data_list);
1050 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1052 _tbm_bufmgr_mutex_unlock();
1058 tbm_bo_export(tbm_bo bo)
1060 tbm_bufmgr bufmgr = gBufMgr;
1063 _tbm_bufmgr_mutex_lock();
1065 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1066 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1068 if (!bufmgr->backend->bo_export) {
1069 _tbm_bufmgr_mutex_unlock();
1073 ret = bufmgr->backend->bo_export(bo);
1075 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1076 TBM_LOG_E("error: bo(%p) tbm_key(%d)\n", bo, ret);
1077 _tbm_bufmgr_mutex_unlock();
1081 TBM_TRACE("bo(%p) tbm_key(%u)\n", bo, ret);
1083 _tbm_bufmgr_mutex_unlock();
1089 tbm_bo_export_fd(tbm_bo bo)
1091 tbm_bufmgr bufmgr = gBufMgr;
1094 _tbm_bufmgr_mutex_lock();
1096 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1097 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1099 if (!bufmgr->backend->bo_export_fd) {
1100 _tbm_bufmgr_mutex_unlock();
1104 ret = bufmgr->backend->bo_export_fd(bo);
1106 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1107 TBM_LOG_E("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1108 _tbm_bufmgr_mutex_unlock();
1112 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1114 _tbm_bufmgr_mutex_unlock();
1120 tbm_bo_get_handle(tbm_bo bo, int device)
1122 tbm_bufmgr bufmgr = gBufMgr;
1123 tbm_bo_handle bo_handle;
1125 _tbm_bufmgr_mutex_lock();
1127 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1128 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1130 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1131 if (bo_handle.ptr == NULL) {
1132 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1133 TBM_LOG_E("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1134 _tbm_bufmgr_mutex_unlock();
1135 return (tbm_bo_handle) NULL;
1138 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1140 _tbm_bufmgr_mutex_unlock();
1146 tbm_bo_map(tbm_bo bo, int device, int opt)
1148 tbm_bufmgr bufmgr = gBufMgr;
1149 tbm_bo_handle bo_handle;
1151 _tbm_bufmgr_mutex_lock();
1153 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1154 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1156 if (!_tbm_bo_lock(bo, device, opt)) {
1157 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1158 TBM_LOG_E("error: fail to lock bo:%p)\n", bo);
1159 _tbm_bufmgr_mutex_unlock();
1160 return (tbm_bo_handle) NULL;
1163 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1164 if (bo_handle.ptr == NULL) {
1165 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1166 TBM_LOG_E("error: fail to map bo:%p\n", bo);
1168 _tbm_bufmgr_mutex_unlock();
1169 return (tbm_bo_handle) NULL;
1172 /* increase the map_count */
1175 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1177 _tbm_bufmgr_mutex_unlock();
1183 tbm_bo_unmap(tbm_bo bo)
1185 tbm_bufmgr bufmgr = gBufMgr;
1188 _tbm_bufmgr_mutex_lock();
1190 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1191 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1193 ret = bufmgr->backend->bo_unmap(bo);
1195 TBM_LOG_E("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1196 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1197 _tbm_bufmgr_mutex_unlock();
1201 /* decrease the map_count */
1204 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1208 _tbm_bufmgr_mutex_unlock();
1214 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1216 tbm_bufmgr bufmgr = gBufMgr;
1219 _tbm_bufmgr_mutex_lock();
1221 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1222 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1223 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1225 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1227 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1228 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1229 TBM_LOG_E("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1230 _tbm_bufmgr_mutex_unlock();
1234 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1237 bo1->priv = bo2->priv;
1240 _tbm_bufmgr_mutex_unlock();
1246 tbm_bo_locked(tbm_bo bo)
1248 tbm_bufmgr bufmgr = gBufMgr;
1250 _tbm_bufmgr_mutex_lock();
1252 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1253 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1255 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1256 TBM_LOG_E("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1257 _tbm_bufmgr_mutex_unlock();
1261 if (bo->lock_cnt > 0) {
1262 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1263 _tbm_bufmgr_mutex_unlock();
1267 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1268 _tbm_bufmgr_mutex_unlock();
1274 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1275 tbm_data_free data_free_func)
1277 tbm_user_data *data;
1279 _tbm_bufmgr_mutex_lock();
1281 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1282 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1284 /* check if the data according to the key exist if so, return false. */
1285 data = user_data_lookup(&bo->user_data_list, key);
1287 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1288 _tbm_bufmgr_mutex_unlock();
1292 data = user_data_create(key, data_free_func);
1294 TBM_LOG_E("error: bo(%p) key(%lu)\n", bo, key);
1295 _tbm_bufmgr_mutex_unlock();
1299 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1301 LIST_ADD(&data->item_link, &bo->user_data_list);
1303 _tbm_bufmgr_mutex_unlock();
1309 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1311 tbm_user_data *old_data;
1313 _tbm_bufmgr_mutex_lock();
1315 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1316 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1318 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1319 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1320 _tbm_bufmgr_mutex_unlock();
1324 old_data = user_data_lookup(&bo->user_data_list, key);
1326 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1327 _tbm_bufmgr_mutex_unlock();
1331 if (old_data->data && old_data->free_func)
1332 old_data->free_func(old_data->data);
1333 old_data->data = data;
1335 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1337 _tbm_bufmgr_mutex_unlock();
1343 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1345 tbm_user_data *old_data;
1347 _tbm_bufmgr_mutex_lock();
1349 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1350 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1352 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1353 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1354 _tbm_bufmgr_mutex_unlock();
1358 old_data = user_data_lookup(&bo->user_data_list, key);
1360 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1362 _tbm_bufmgr_mutex_unlock();
1366 *data = old_data->data;
1368 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1370 _tbm_bufmgr_mutex_unlock();
1376 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1378 tbm_user_data *old_data;
1380 _tbm_bufmgr_mutex_lock();
1382 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1383 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1385 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1386 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1387 _tbm_bufmgr_mutex_unlock();
1391 old_data = user_data_lookup(&bo->user_data_list, key);
1393 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1394 _tbm_bufmgr_mutex_unlock();
1398 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1400 user_data_delete(old_data);
1402 _tbm_bufmgr_mutex_unlock();
1408 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1410 unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1412 _tbm_bufmgr_mutex_lock();
1414 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1415 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1417 TBM_TRACE("tbm_bufmgr(%p) capability(%u)\n", bufmgr, bufmgr->capabilities);
1419 capabilities = bufmgr->capabilities;
1421 _tbm_bufmgr_mutex_unlock();
1423 return capabilities;
1427 tbm_bo_get_flags(tbm_bo bo)
1431 _tbm_bufmgr_mutex_lock();
1433 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1434 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1438 TBM_TRACE("bo(%p)\n", bo);
1440 _tbm_bufmgr_mutex_unlock();
1445 /* LCOV_EXCL_START */
1447 tbm_get_last_error(void)
1449 return tbm_last_error;
1453 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1455 char app_name[255] = {0,}, title[512] = {0,};
1456 tbm_surface_debug_data *debug_old_data = NULL;
1458 pthread_mutex_lock(&gLock);
1460 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1461 TBM_LOG_E("invalid bufmgr\n");
1462 pthread_mutex_unlock(&gLock);
1467 _tbm_util_get_appname_from_pid(getpid(), app_name);
1468 _tbm_util_get_appname_brief(app_name);
1469 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1470 app_name, getpid());
1472 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1474 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1475 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
1476 strncat(title, " ", 3);
1477 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1481 TBM_DEBUG("[tbm_surface information]\n");
1482 TBM_DEBUG("%s\n", title);
1484 /* show the tbm_surface information in surf_list */
1485 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1486 tbm_surface_h surf = NULL;
1489 LIST_FOR_EACH_ENTRY(surf, &bufmgr->surf_list, item_link) {
1490 char data[512] = {0,};
1494 pid = _tbm_surface_internal_get_debug_pid(surf);
1496 /* if pid is null, set the self_pid */
1500 memset(app_name, 0x0, 255 * sizeof(char));
1501 _tbm_util_get_appname_from_pid(pid, app_name);
1502 _tbm_util_get_appname_brief(app_name);
1504 snprintf(data, 255, "%-2d %-9p %-4d %-5u %-6u %-3u %-6u %-2d %-2d %-3d %-8s %-15s",
1511 surf->info.size / 1024,
1515 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1518 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1519 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
1522 strncat(data, " ", 3);
1524 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1526 strncat(data, value, strlen(value) + 1);
1528 strncat(data, "none", 5);
1531 TBM_DEBUG("%s\n", data);
1533 for (i = 0; i < surf->num_bos; i++) {
1534 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1536 surf->bos[i]->ref_cnt,
1537 bufmgr->backend->bo_size(surf->bos[i]) / 1024);
1541 TBM_DEBUG("no tbm_surfaces.\n");
1544 TBM_DEBUG("[tbm_bo information]\n");
1545 TBM_DEBUG("no bo refcnt size lock_cnt map_cnt flags surface\n");
1547 /* show the tbm_bo information in bo_list */
1548 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1552 LIST_FOR_EACH_ENTRY(bo, &bufmgr->bo_list, item_link) {
1553 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4u %-3d %-11p\n",
1557 bufmgr->backend->bo_size(bo) / 1024,
1564 TBM_DEBUG("no tbm_bos.\n");
1567 TBM_DEBUG("===============================================================\n");
1569 pthread_mutex_unlock(&gLock);
1573 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1575 _tbm_bufmgr_mutex_lock();
1577 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1578 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1581 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1585 _tbm_bufmgr_mutex_unlock();
1589 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1591 pthread_mutex_lock(&gLock);
1594 TBM_LOG_D("count=%d onoff=%d\n", count, onoff);
1596 tbm_surface_internal_dump_end();
1601 TBM_LOG_E("path is null");
1602 pthread_mutex_unlock(&gLock);
1605 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1607 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1608 TBM_LOG_E("Fail to get tbm_surface size.\n");
1609 pthread_mutex_unlock(&gLock);
1613 tbm_surface_internal_dump_start(path, w, h, count);
1617 pthread_mutex_unlock(&gLock);
1622 tbm_bufmgr_debug_dump_all(char *path)
1624 int w, h, count = 0;
1625 tbm_surface_h surface = NULL;
1627 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1628 TBM_LOG_D("path=%s\n", path);
1630 pthread_mutex_lock(&gLock);
1632 count = _tbm_util_get_max_surface_size(&w, &h);
1634 TBM_LOG_E("No tbm_surface.\n");
1635 pthread_mutex_unlock(&gLock);
1639 tbm_surface_internal_dump_start(path, w, h, count);
1641 LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
1642 tbm_surface_internal_dump_buffer(surface, "dump_all");
1644 tbm_surface_internal_dump_end();
1646 pthread_mutex_unlock(&gLock);
1651 /* internal function */
1653 _tbm_bufmgr_get_bufmgr(void)
1659 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1661 _tbm_bufmgr_mutex_lock();
1663 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1664 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1666 bo->surface = surface;
1668 _tbm_bufmgr_mutex_unlock();
1674 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1678 _tbm_bufmgr_mutex_lock();
1680 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1682 if (!bufmgr->backend->bufmgr_bind_native_display) {
1683 TBM_TRACE("skip: tbm_bufmgr(%p) NativeDisplay(%p)\n",
1684 bufmgr, NativeDisplay);
1685 _tbm_bufmgr_mutex_unlock();
1689 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1691 TBM_LOG_E("error: tbm_bufmgr(%p) NativeDisplay(%p)\n",
1692 bufmgr, NativeDisplay);
1693 _tbm_bufmgr_mutex_unlock();
1697 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1699 _tbm_bufmgr_mutex_unlock();
1703 /* LCOV_EXCL_STOP */