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: tbm_bufmgr mutex init\n");
120 tbm_bufmgr_mutex_init = true;
126 _tbm_bufmgr_mutex_lock(void)
128 if (!_tbm_bufmgr_mutex_init())
131 pthread_mutex_lock(&tbm_bufmgr_lock);
135 _tbm_bufmgr_mutex_unlock(void)
137 pthread_mutex_unlock(&tbm_bufmgr_lock);
140 char * tbm_flag_to_str(int f)
142 static char str[255];
144 if (f == TBM_BO_DEFAULT)
145 snprintf(str, 255, "DEFAULT\n");
147 if (f & TBM_BO_SCANOUT)
148 c = snprintf(&str[c], 255, "SCANOUT,");
149 if (f & TBM_BO_NONCACHABLE)
150 c = snprintf(&str[c], 255, "NONCACHABLE,");
152 c = snprintf(&str[c], 255, "WC");
157 /* LCOV_EXCL_START */
158 static int last_chk_bo_cnt = 0;
160 _tbm_util_check_bo_cnt(tbm_bufmgr bufmgr)
162 if (bufmgr->bo_cnt >= 500 && ((bufmgr->bo_cnt % 20) == 0)) {
163 if (bufmgr->bo_cnt > last_chk_bo_cnt) {
164 TBM_DEBUG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
165 tbm_bufmgr_debug_show(bufmgr);
166 last_chk_bo_cnt = bufmgr->bo_cnt;
172 _tbm_util_get_max_surface_size(int * w, int * h)
175 tbm_surface_h surface = NULL, tmp = NULL;
176 tbm_surface_info_s info;
184 if (!LIST_IS_EMPTY(&gBufMgr->surf_list)) {
185 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
186 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
188 if (*w < info.width) *w = info.width;
189 if (*h < info.height) *h = info.height;
198 _tbm_util_get_appname_brief(char *brief)
202 char temp[255] = {0,};
203 char *saveptr = NULL;
205 token = strtok_r(brief, delim, &saveptr);
207 while (token != NULL) {
208 memset(temp, 0x00, 255 * sizeof(char));
209 strncpy(temp, token, 254 * sizeof(char));
210 token = strtok_r(NULL, delim, &saveptr);
213 snprintf(brief, sizeof(temp), "%s", temp);
217 _tbm_util_get_appname_from_pid(long pid, char *str)
222 char fn_cmdline[255] = {0,};
223 char cmdline[255] = {0,};
225 snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", app_pid);
227 fp = fopen(fn_cmdline, "r");
229 fprintf(stderr, "cannot file open /proc/%ld/cmdline", app_pid);
233 if (!fgets(cmdline, 255, fp)) {
234 fprintf(stderr, "fail to get appname for pid(%ld)\n", app_pid);
240 len = strlen(cmdline);
242 memset(cmdline, 0x00, 255);
246 snprintf(str, sizeof(cmdline), "%s", cmdline);
251 *user_data_lookup(struct list_head *user_data_list, unsigned long key)
253 tbm_user_data *user_data = NULL;
254 tbm_user_data *old_data = NULL, *tmp = NULL;
256 if (!LIST_IS_EMPTY(user_data_list)) {
257 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, user_data_list, item_link) {
258 if (old_data->key == key) {
259 user_data = old_data;
269 *user_data_create(unsigned long key, tbm_data_free data_free_func)
271 tbm_user_data *user_data = NULL;
273 user_data = calloc(1, sizeof(tbm_user_data));
277 user_data->key = key;
278 user_data->free_func = data_free_func;
279 user_data->data = (void *)0;
285 user_data_delete(tbm_user_data *user_data)
287 if (user_data->data && user_data->free_func)
288 user_data->free_func(user_data->data);
290 LIST_DEL(&user_data->item_link);
296 _bo_lock(tbm_bo bo, int device, int opt)
298 tbm_bufmgr bufmgr = bo->bufmgr;
301 if (bufmgr->backend->bo_lock)
302 ret = bufmgr->backend->bo_lock(bo, device, opt);
310 _bo_unlock(tbm_bo bo)
312 tbm_bufmgr bufmgr = bo->bufmgr;
314 if (bufmgr->backend->bo_unlock)
315 bufmgr->backend->bo_unlock(bo);
319 _tbm_bo_lock(tbm_bo bo, int device, int opt)
321 tbm_bufmgr bufmgr = NULL;
330 /* do not try to lock the bo */
331 if (bufmgr->lock_type == LOCK_TRY_NEVER)
334 if (bo->lock_cnt < 0) {
335 TBM_LOG_E("error bo:%p LOCK_CNT=%d\n",
340 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
341 if (bo->lock_cnt == 0) {
342 _tbm_bufmgr_mutex_unlock();
343 ret = _bo_lock(bo, device, opt);
344 _tbm_bufmgr_mutex_lock();
349 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
350 _tbm_bufmgr_mutex_unlock();
351 ret = _bo_lock(bo, device, opt);
352 _tbm_bufmgr_mutex_lock();
356 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
360 TBM_DBG_LOCK(">> LOCK bo:%p(%d->%d)\n",
361 bo, old, bo->lock_cnt);
367 _tbm_bo_unlock(tbm_bo bo)
369 tbm_bufmgr bufmgr = NULL;
378 /* do not try to unlock the bo */
379 if (bufmgr->lock_type == LOCK_TRY_NEVER)
383 if (bufmgr->lock_type == LOCK_TRY_ONCE) {
384 if (bo->lock_cnt > 0) {
386 if (bo->lock_cnt == 0)
389 } else if (bufmgr->lock_type == LOCK_TRY_ALWAYS) {
390 if (bo->lock_cnt > 0) {
395 TBM_LOG_E("error bo:%p lock_type is wrong.\n",
399 if (bo->lock_cnt < 0)
402 TBM_DBG_LOCK(">> UNLOCK bo:%p(%d->%d)\n",
403 bo, old, bo->lock_cnt);
407 _tbm_bo_is_valid(tbm_bo bo)
409 tbm_bo old_data = NULL, tmp = NULL;
414 if (gBufMgr == NULL) {
415 TBM_LOG_E("error tbm_bufmgr was deinited\n");
419 if (!LIST_IS_EMPTY(&gBufMgr->bo_list)) {
420 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &gBufMgr->bo_list, item_link) {
429 /* LCOV_EXCL_START */
431 _check_version(TBMModuleVersionInfo *data)
436 abimaj = GET_ABI_MAJOR(data->abiversion);
437 abimin = GET_ABI_MINOR(data->abiversion);
439 TBM_DBG("TBM module %s: vendor=\"%s\" ABI=%d,%d\n",
440 data->modname ? data->modname : "UNKNOWN!",
441 data->vendor ? data->vendor : "UNKNOWN!", abimaj, abimin);
443 vermaj = GET_ABI_MAJOR(TBM_ABI_VERSION);
444 vermin = GET_ABI_MINOR(TBM_ABI_VERSION);
446 TBM_DBG("TBM ABI version %d.%d\n",
449 if (abimaj != vermaj) {
450 TBM_LOG_E("TBM module ABI major ver(%d) doesn't match the TBM's ver(%d)\n",
453 } else if (abimin > vermin) {
454 TBM_LOG_E("TBM module ABI minor ver(%d) is newer than the TBM's ver(%d)\n",
462 _tbm_bufmgr_load_module(tbm_bufmgr bufmgr, int fd, const char *file)
464 char path[PATH_MAX] = { 0, };
465 TBMModuleData *initdata = NULL;
468 snprintf(path, sizeof(path), BUFMGR_MODULE_DIR "/%s", file);
470 module_data = dlopen(path, RTLD_LAZY);
472 TBM_LOG_E("failed to load module: %s(%s)\n",
477 initdata = dlsym(module_data, "tbmModuleData");
480 TBMModuleVersionInfo *vers;
482 vers = initdata->vers;
483 init = initdata->init;
486 if (!_check_version(vers)) {
487 dlclose(module_data);
491 TBM_LOG_E("Error: module does not supply version information.\n");
493 dlclose(module_data);
498 if (!init(bufmgr, fd)) {
499 TBM_LOG_E("Fail to init module(%s)\n",
501 dlclose(module_data);
505 if (!bufmgr->backend || !bufmgr->backend->priv) {
506 TBM_LOG_E("Error: module(%s) wrong operation. Check backend or backend's priv.\n",
508 dlclose(module_data);
512 TBM_LOG_E("Error: module does not supply init symbol.\n");
513 dlclose(module_data);
517 TBM_LOG_E("Error: module does not have data object.\n");
518 dlclose(module_data);
522 bufmgr->module_data = module_data;
524 TBM_DBG("Success to load module(%s)\n",
531 _tbm_load_module(tbm_bufmgr bufmgr, int fd)
533 struct dirent **namelist;
534 const char *p = NULL;
538 /* load bufmgr priv from default lib */
539 ret = _tbm_bufmgr_load_module(bufmgr, fd, DEFAULT_LIB);
541 /* load bufmgr priv from configured path */
543 n = scandir(BUFMGR_MODULE_DIR, &namelist, 0, alphasort);
545 TBM_LOG_E("no files : %s\n",
549 if (!ret && strstr(namelist[n]->d_name, PREFIX_LIB)) {
550 p = strstr(namelist[n]->d_name, SUFFIX_LIB);
551 if (p && !strcmp(p, SUFFIX_LIB))
552 ret = _tbm_bufmgr_load_module(bufmgr, fd, namelist[n]->d_name);
565 tbm_bufmgr_init(int fd)
569 #ifdef TBM_BUFMGR_INIT_TIME
570 struct timeval start_tv, end_tv;
573 pthread_mutex_lock(&gLock);
575 #ifdef TBM_BUFMGR_INIT_TIME
576 /* get the start tv */
577 gettimeofday(&start_tv, NULL);
580 /* LCOV_EXCL_START */
582 env = getenv("TBM_DLOG");
585 TBM_LOG_D("TBM_DLOG=%s\n", env);
592 env = getenv("TBM_DEBUG");
595 TBM_LOG_D("TBM_DEBUG=%s\n", env);
602 env = getenv("TBM_TRACE");
605 TBM_LOG_D("TBM_TRACE=%s\n", env);
612 /* initialize buffer manager */
614 gBufMgr->ref_count++;
615 TBM_TRACE("reuse tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
616 pthread_mutex_unlock(&gLock);
620 TBM_DBG("bufmgr init\n");
622 /* allocate bufmgr */
623 gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
625 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
626 TBM_TRACE("error: fail to alloc bufmgr fd(%d)\n", fd);
627 pthread_mutex_unlock(&gLock);
633 /* load bufmgr priv from env */
634 if (!_tbm_load_module(gBufMgr, gBufMgr->fd)) {
635 /* LCOV_EXCL_START */
636 _tbm_set_last_result(TBM_BO_ERROR_LOAD_MODULE_FAILED);
637 TBM_LOG_E("error : Fail to load bufmgr backend\n");
640 pthread_mutex_unlock(&gLock);
645 /* log for tbm backend_flag */
646 TBM_DBG("backend flag:%x:", gBufMgr->backend->flags);
649 gBufMgr->ref_count = 1;
651 TBM_DBG("create tizen bufmgr:%p ref_count:%d\n",
652 gBufMgr, gBufMgr->ref_count);
654 /* setup the lock_type */
655 env = getenv("BUFMGR_LOCK_TYPE");
656 if (env && !strcmp(env, "always"))
657 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
658 else if (env && !strcmp(env, "none"))
659 gBufMgr->lock_type = LOCK_TRY_NEVER;
660 else if (env && !strcmp(env, "once"))
661 gBufMgr->lock_type = LOCK_TRY_ONCE;
663 gBufMgr->lock_type = LOCK_TRY_ALWAYS;
665 TBM_DBG("BUFMGR_LOCK_TYPE=%s\n",
666 env ? env : "default:once");
668 TBM_TRACE("create tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, fd);
670 /* intialize bo_list */
671 LIST_INITHEAD(&gBufMgr->bo_list);
673 /* intialize surf_list */
674 LIST_INITHEAD(&gBufMgr->surf_list);
676 /* intialize surf_list */
677 LIST_INITHEAD(&gBufMgr->surf_queue_list);
679 /* intialize debug_key_list */
680 LIST_INITHEAD(&gBufMgr->debug_key_list);
682 #ifdef TBM_BUFMGR_INIT_TIME
684 gettimeofday(&end_tv, NULL);
685 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)));
688 pthread_mutex_unlock(&gLock);
694 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
696 TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
701 tbm_surface_h surf = NULL;
702 tbm_surface_h tmp_surf = NULL;
704 pthread_mutex_lock(&gLock);
707 TBM_LOG_E("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
708 pthread_mutex_unlock(&gLock);
713 if (bufmgr->ref_count > 0) {
714 TBM_TRACE("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
715 pthread_mutex_unlock(&gLock);
719 /* destroy bo_list */
720 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
721 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
722 TBM_LOG_E("Un-freed bo(%p, ref:%d)\n",
729 /* destroy surf_list */
730 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
731 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
732 TBM_LOG_E("Un-freed surf(%p, ref:%d)\n",
734 tbm_surface_destroy(surf);
738 /* destroy bufmgr priv */
739 bufmgr->backend->bufmgr_deinit(bufmgr->backend->priv);
740 bufmgr->backend->priv = NULL;
741 tbm_backend_free(bufmgr->backend);
742 bufmgr->backend = NULL;
744 TBM_TRACE("destroy tbm_bufmgr(%p)\n", bufmgr);
746 dlclose(bufmgr->module_data);
755 pthread_mutex_unlock(&gLock);
759 tbm_bo_size(tbm_bo bo)
761 tbm_bufmgr bufmgr = NULL;
764 _tbm_bufmgr_mutex_lock();
766 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
767 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
771 size = bufmgr->backend->bo_size(bo);
773 TBM_TRACE("bo(%p) size(%d)\n", bo, size);
775 _tbm_bufmgr_mutex_unlock();
781 tbm_bo_ref(tbm_bo bo)
783 _tbm_bufmgr_mutex_lock();
785 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
786 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), NULL);
790 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt);
792 _tbm_bufmgr_mutex_unlock();
798 tbm_bo_unref(tbm_bo bo)
800 tbm_bufmgr bufmgr = NULL;
801 tbm_user_data *old_data = NULL, *tmp = NULL;
803 _tbm_bufmgr_mutex_lock();
805 TBM_BUFMGR_RETURN_IF_FAIL(gBufMgr);
806 TBM_BUFMGR_RETURN_IF_FAIL(_tbm_bo_is_valid(bo));
810 TBM_TRACE("bo(%p) ref_cnt(%d)\n", bo, bo->ref_cnt - 1);
812 if (bo->ref_cnt <= 0) {
813 _tbm_bufmgr_mutex_unlock();
818 if (bo->ref_cnt == 0) {
819 /* destory the user_data_list */
820 if (!LIST_IS_EMPTY(&bo->user_data_list)) {
821 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bo->user_data_list, item_link) {
822 TBM_DBG("free user_data\n");
823 user_data_delete(old_data);
827 if (bo->lock_cnt > 0) {
828 TBM_LOG_E("error lock_cnt:%d\n",
833 /* call the bo_free */
834 bufmgr->backend->bo_free(bo);
837 LIST_DEL(&bo->item_link);
843 _tbm_bufmgr_mutex_unlock();
847 tbm_bo_alloc(tbm_bufmgr bufmgr, int size, int flags)
850 void *bo_priv = NULL;
852 _tbm_bufmgr_mutex_lock();
854 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
855 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
856 TBM_BUFMGR_RETURN_VAL_IF_FAIL(size > 0, NULL);
858 bo = calloc(1, sizeof(struct _tbm_bo));
860 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
861 _tbm_set_last_result(TBM_BO_ERROR_HEAP_ALLOC_FAILED);
862 _tbm_bufmgr_mutex_unlock();
866 _tbm_util_check_bo_cnt(bufmgr);
871 bo_priv = bufmgr->backend->bo_alloc(bo, size, flags);
873 TBM_TRACE("error: fail to create of tbm_bo size(%d) flag(%s)\n", size, tbm_flag_to_str(flags));
874 _tbm_set_last_result(TBM_BO_ERROR_BO_ALLOC_FAILED);
876 _tbm_bufmgr_mutex_unlock();
884 TBM_TRACE("bo(%p) size(%d) refcnt(%d), flag(%s)\n", bo, size, bo->ref_cnt, tbm_flag_to_str(bo->flags));
886 LIST_INITHEAD(&bo->user_data_list);
888 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
890 _tbm_bufmgr_mutex_unlock();
896 tbm_bo_import(tbm_bufmgr bufmgr, unsigned int key)
901 void *bo_priv = NULL;
903 _tbm_bufmgr_mutex_lock();
905 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
906 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
908 if (!bufmgr->backend->bo_import) {
909 _tbm_bufmgr_mutex_unlock();
913 _tbm_util_check_bo_cnt(bufmgr);
915 bo = calloc(1, sizeof(struct _tbm_bo));
917 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
918 _tbm_bufmgr_mutex_unlock();
926 bo_priv = bufmgr->backend->bo_import(bo, key);
928 TBM_TRACE("error: fail to import of tbm_bo by key(%d)\n", key);
929 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FAILED);
931 _tbm_bufmgr_mutex_unlock();
935 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
936 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
937 if (bo2->priv == bo_priv) {
938 TBM_TRACE("find bo(%p) ref(%d) key(%d) flag(%s) in list\n",
939 bo2, bo2->ref_cnt, key, tbm_flag_to_str(bo2->flags));
942 _tbm_bufmgr_mutex_unlock();
951 if (bufmgr->backend->bo_get_flags)
952 bo->flags = bufmgr->backend->bo_get_flags(bo);
954 bo->flags = TBM_BO_DEFAULT;
956 TBM_TRACE("import new bo(%p) ref(%d) key(%d) flag(%s) in list\n",
957 bo, bo->ref_cnt, key, tbm_flag_to_str(bo->flags));
959 LIST_INITHEAD(&bo->user_data_list);
961 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
963 _tbm_bufmgr_mutex_unlock();
969 tbm_bo_import_fd(tbm_bufmgr bufmgr, tbm_fd fd)
974 void *bo_priv = NULL;
976 _tbm_bufmgr_mutex_lock();
978 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
979 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
981 if (!bufmgr->backend->bo_import_fd) {
982 _tbm_bufmgr_mutex_unlock();
986 _tbm_util_check_bo_cnt(bufmgr);
988 bo = calloc(1, sizeof(struct _tbm_bo));
990 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
991 _tbm_bufmgr_mutex_unlock();
999 bo_priv = bufmgr->backend->bo_import_fd(bo, fd);
1001 TBM_TRACE("error: fail to import tbm_bo by tbm_fd(%d)\n", fd);
1002 _tbm_set_last_result(TBM_BO_ERROR_IMPORT_FD_FAILED);
1004 _tbm_bufmgr_mutex_unlock();
1008 if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
1009 LIST_FOR_EACH_ENTRY_SAFE(bo2, tmp, &bufmgr->bo_list, item_link) {
1010 if (bo2->priv == bo_priv) {
1011 TBM_TRACE("find bo(%p) ref(%d) fd(%d) flag(%s) in list\n",
1012 bo2, bo2->ref_cnt, fd, tbm_flag_to_str(bo2->flags));
1015 _tbm_bufmgr_mutex_unlock();
1024 if (bufmgr->backend->bo_get_flags)
1025 bo->flags = bufmgr->backend->bo_get_flags(bo);
1027 bo->flags = TBM_BO_DEFAULT;
1029 TBM_TRACE("import bo(%p) ref(%d) fd(%d) flag(%s)in list\n",
1030 bo, bo->ref_cnt, fd, tbm_flag_to_str(bo->flags));
1032 LIST_INITHEAD(&bo->user_data_list);
1034 LIST_ADD(&bo->item_link, &bufmgr->bo_list);
1036 _tbm_bufmgr_mutex_unlock();
1042 tbm_bo_export(tbm_bo bo)
1044 tbm_bufmgr bufmgr = NULL;
1047 _tbm_bufmgr_mutex_lock();
1049 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1050 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1054 if (!bufmgr->backend->bo_export) {
1055 _tbm_bufmgr_mutex_unlock();
1059 ret = bufmgr->backend->bo_export(bo);
1061 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FAILED);
1062 TBM_TRACE("error: bo(%p) tbm_key(%d)\n", bo, ret);
1063 _tbm_bufmgr_mutex_unlock();
1067 TBM_TRACE("bo(%p) tbm_key(%d)\n", bo, ret);
1069 _tbm_bufmgr_mutex_unlock();
1075 tbm_bo_export_fd(tbm_bo bo)
1077 tbm_bufmgr bufmgr = NULL;
1080 _tbm_bufmgr_mutex_lock();
1082 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), -1);
1083 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), -1);
1087 if (!bufmgr->backend->bo_export_fd) {
1088 _tbm_bufmgr_mutex_unlock();
1092 ret = bufmgr->backend->bo_export_fd(bo);
1094 _tbm_set_last_result(TBM_BO_ERROR_EXPORT_FD_FAILED);
1095 TBM_TRACE("error: bo(%p) tbm_fd(%d)\n", bo, ret);
1096 _tbm_bufmgr_mutex_unlock();
1100 TBM_TRACE("bo(%p) tbm_fd(%d)\n", bo, ret);
1102 _tbm_bufmgr_mutex_unlock();
1108 tbm_bo_get_handle(tbm_bo bo, int device)
1110 tbm_bufmgr bufmgr = NULL;
1111 tbm_bo_handle bo_handle;
1113 _tbm_bufmgr_mutex_lock();
1115 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1116 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1120 bo_handle = bufmgr->backend->bo_get_handle(bo, device);
1121 if (bo_handle.ptr == NULL) {
1122 _tbm_set_last_result(TBM_BO_ERROR_GET_HANDLE_FAILED);
1123 TBM_TRACE("error: bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1124 _tbm_bufmgr_mutex_unlock();
1125 return (tbm_bo_handle) NULL;
1128 TBM_TRACE("bo(%p) bo_handle(%p)\n", bo, bo_handle.ptr);
1130 _tbm_bufmgr_mutex_unlock();
1136 tbm_bo_map(tbm_bo bo, int device, int opt)
1138 tbm_bufmgr bufmgr = NULL;
1139 tbm_bo_handle bo_handle;
1141 _tbm_bufmgr_mutex_lock();
1143 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), (tbm_bo_handle) NULL);
1144 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), (tbm_bo_handle) NULL);
1148 if (!_tbm_bo_lock(bo, device, opt)) {
1149 _tbm_set_last_result(TBM_BO_ERROR_LOCK_FAILED);
1150 TBM_TRACE("error: fail to lock bo:%p)\n", bo);
1151 _tbm_bufmgr_mutex_unlock();
1152 return (tbm_bo_handle) NULL;
1155 bo_handle = bufmgr->backend->bo_map(bo, device, opt);
1156 if (bo_handle.ptr == NULL) {
1157 _tbm_set_last_result(TBM_BO_ERROR_MAP_FAILED);
1158 TBM_TRACE("error: fail to map bo:%p\n", bo);
1160 _tbm_bufmgr_mutex_unlock();
1161 return (tbm_bo_handle) NULL;
1164 /* increase the map_count */
1167 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1169 _tbm_bufmgr_mutex_unlock();
1175 tbm_bo_unmap(tbm_bo bo)
1177 tbm_bufmgr bufmgr = NULL;
1180 _tbm_bufmgr_mutex_lock();
1182 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1183 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1187 ret = bufmgr->backend->bo_unmap(bo);
1189 TBM_TRACE("error: bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1190 _tbm_set_last_result(TBM_BO_ERROR_UNMAP_FAILED);
1191 _tbm_bufmgr_mutex_unlock();
1195 /* decrease the map_count */
1198 TBM_TRACE("bo(%p) map_cnt(%d)\n", bo, bo->map_cnt);
1202 _tbm_bufmgr_mutex_unlock();
1208 tbm_bo_swap(tbm_bo bo1, tbm_bo bo2)
1210 tbm_bufmgr bufmgr = NULL;
1213 _tbm_bufmgr_mutex_lock();
1215 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1216 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo1), 0);
1217 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo2), 0);
1221 TBM_TRACE("before: bo1(%p) bo2(%p)\n", bo1, bo2);
1223 if (bufmgr->backend->bo_size(bo1) != bufmgr->backend->bo_size(bo2)) {
1224 _tbm_set_last_result(TBM_BO_ERROR_SWAP_FAILED);
1225 TBM_TRACE("error: bo1(%p) bo2(%p)\n", bo1, bo2);
1226 _tbm_bufmgr_mutex_unlock();
1230 TBM_TRACE("after: bo1(%p) bo2(%p)\n", bo1, bo2);
1233 bo1->priv = bo2->priv;
1236 _tbm_bufmgr_mutex_unlock();
1242 tbm_bo_locked(tbm_bo bo)
1244 tbm_bufmgr bufmgr = NULL;
1246 _tbm_bufmgr_mutex_lock();
1248 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1249 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1253 if (bufmgr->lock_type == LOCK_TRY_NEVER) {
1254 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1255 _tbm_bufmgr_mutex_unlock();
1259 if (bo->lock_cnt > 0) {
1260 TBM_TRACE("error: bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1261 _tbm_bufmgr_mutex_unlock();
1265 TBM_TRACE("bo(%p) lock_cnt(%d)\n", bo, bo->lock_cnt);
1266 _tbm_bufmgr_mutex_unlock();
1272 tbm_bo_add_user_data(tbm_bo bo, unsigned long key,
1273 tbm_data_free data_free_func)
1275 tbm_user_data *data;
1277 _tbm_bufmgr_mutex_lock();
1279 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1280 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1282 /* check if the data according to the key exist if so, return false. */
1283 data = user_data_lookup(&bo->user_data_list, key);
1285 TBM_TRACE("warning: user data already exist key(%ld)\n", key);
1286 _tbm_bufmgr_mutex_unlock();
1290 data = user_data_create(key, data_free_func);
1292 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1293 _tbm_bufmgr_mutex_unlock();
1297 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, data->data);
1299 LIST_ADD(&data->item_link, &bo->user_data_list);
1301 _tbm_bufmgr_mutex_unlock();
1307 tbm_bo_set_user_data(tbm_bo bo, unsigned long key, void *data)
1309 tbm_user_data *old_data;
1311 _tbm_bufmgr_mutex_lock();
1313 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1314 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1316 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1317 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1318 _tbm_bufmgr_mutex_unlock();
1322 old_data = user_data_lookup(&bo->user_data_list, key);
1324 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1325 _tbm_bufmgr_mutex_unlock();
1329 if (old_data->data && old_data->free_func)
1330 old_data->free_func(old_data->data);
1332 old_data->data = data;
1334 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1336 _tbm_bufmgr_mutex_unlock();
1342 tbm_bo_get_user_data(tbm_bo bo, unsigned long key, void **data)
1344 tbm_user_data *old_data;
1346 _tbm_bufmgr_mutex_lock();
1348 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1349 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1351 if (!data || LIST_IS_EMPTY(&bo->user_data_list)) {
1352 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1353 _tbm_bufmgr_mutex_unlock();
1357 old_data = user_data_lookup(&bo->user_data_list, key);
1359 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1361 _tbm_bufmgr_mutex_unlock();
1365 *data = old_data->data;
1367 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1369 _tbm_bufmgr_mutex_unlock();
1375 tbm_bo_delete_user_data(tbm_bo bo, unsigned long key)
1377 tbm_user_data *old_data = (void *)0;
1379 _tbm_bufmgr_mutex_lock();
1381 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1382 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1384 if (LIST_IS_EMPTY(&bo->user_data_list)) {
1385 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1386 _tbm_bufmgr_mutex_unlock();
1390 old_data = user_data_lookup(&bo->user_data_list, key);
1392 TBM_TRACE("error: bo(%p) key(%lu)\n", bo, key);
1393 _tbm_bufmgr_mutex_unlock();
1397 TBM_TRACE("bo(%p) key(%lu) data(%p)\n", bo, key, old_data->data);
1399 user_data_delete(old_data);
1401 _tbm_bufmgr_mutex_unlock();
1407 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
1409 int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
1411 _tbm_bufmgr_mutex_lock();
1413 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
1414 TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
1416 TBM_TRACE("tbm_bufmgr(%p) capability(%d)\n", bufmgr, bufmgr->capabilities);
1418 capabilities = bufmgr->capabilities;
1420 _tbm_bufmgr_mutex_unlock();
1422 return capabilities;
1426 tbm_bo_get_flags(tbm_bo bo)
1430 _tbm_bufmgr_mutex_lock();
1432 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1433 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1437 TBM_TRACE("bo(%p)\n", bo);
1439 _tbm_bufmgr_mutex_unlock();
1444 /* LCOV_EXCL_START */
1446 tbm_get_last_error(void)
1448 return tbm_last_error;
1452 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
1454 tbm_bo bo = NULL, tmp_bo = NULL;
1456 tbm_surface_h surf = NULL, tmp_surf = NULL;
1459 char app_name[255] = {0,};
1460 unsigned int pid = 0;
1461 char title[255] = {0,};
1462 char data[255] = {0,};
1463 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
1465 pthread_mutex_lock(&gLock);
1467 if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
1468 TBM_LOG_E("invalid bufmgr\n");
1469 pthread_mutex_unlock(&gLock);
1474 _tbm_util_get_appname_from_pid(getpid(), app_name);
1475 _tbm_util_get_appname_brief(app_name);
1476 TBM_DEBUG("============TBM DEBUG: %s(%d)===========================\n",
1477 app_name, getpid());
1478 memset(app_name, 0x0, 255 * sizeof(char));
1479 snprintf(title, 255, "%s", "no surface refcnt width height bpp size n_b n_p flags format app_name ");
1480 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1481 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1482 strncat(title, " ", 3);
1483 strncat(title, debug_old_data->key, strlen(debug_old_data->key) + 1);
1487 TBM_DEBUG("[tbm_surface information]\n");
1488 TBM_DEBUG("%s\n", title);
1489 /* show the tbm_surface information in surf_list */
1490 if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
1493 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp_surf, &bufmgr->surf_list, item_link) {
1494 pid = _tbm_surface_internal_get_debug_pid(surf);
1496 /* if pid is null, set the self_pid */
1500 _tbm_util_get_appname_from_pid(pid, app_name);
1501 _tbm_util_get_appname_brief(app_name);
1503 snprintf(data, 255, "%-2d %-9p %-4d %-5d %-6d %-3d %-6d %-2d %-2d %-3d %-8s %-15s",
1510 surf->info.size / 1024,
1514 _tbm_surface_internal_format_to_str(surf->info.format) + 11,
1517 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1518 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
1519 strncat(data, " ", 3);
1521 value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
1523 strncat(data, value, strlen(value) + 1);
1525 strncat(data, "none", 5);
1528 TBM_DEBUG("%s\n", data);
1530 for (i = 0; i < surf->num_bos; i++) {
1531 TBM_DEBUG(" bo:%-12p %-26d%-10d\n",
1533 surf->bos[i]->ref_cnt,
1534 tbm_bo_size(surf->bos[i]) / 1024);
1537 memset(app_name, 0x0, 255 * sizeof(char));
1540 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)) {
1549 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp_bo, &bufmgr->bo_list, item_link) {
1550 TBM_DEBUG("%-4d%-11p %-4d %-6d %-5d %-4d %-3d %-11p\n",
1554 tbm_bo_size(bo) / 1024,
1561 TBM_DEBUG("no tbm_bos.\n");
1565 TBM_DEBUG("===============================================================\n");
1567 pthread_mutex_unlock(&gLock);
1571 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
1573 _tbm_bufmgr_mutex_lock();
1575 TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
1576 TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
1579 TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
1583 _tbm_bufmgr_mutex_unlock();
1587 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
1591 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1592 TBM_LOG_D("path=%s count=%d onoff=%d\n", path, count, onoff);
1594 pthread_mutex_lock(&gLock);
1597 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
1598 TBM_LOG_I("No tbm_surface.\n");
1599 pthread_mutex_unlock(&gLock);
1603 tbm_surface_internal_dump_start(path, w, h, count);
1605 } else if (onoff == 0) {
1606 tbm_surface_internal_dump_end();
1609 pthread_mutex_unlock(&gLock);
1613 pthread_mutex_unlock(&gLock);
1618 tbm_bufmgr_debug_dump_all(char *path)
1620 int w = 0, h = 0, count = 0;
1621 tbm_surface_h surface = NULL, tmp = NULL;
1623 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
1624 TBM_LOG_D("path=%s\n", path);
1626 pthread_mutex_lock(&gLock);
1628 count = _tbm_util_get_max_surface_size(&w, &h);
1630 TBM_LOG_I("No tbm_surface.\n");
1631 pthread_mutex_unlock(&gLock);
1635 tbm_surface_internal_dump_start(path, w, h, count);
1637 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &gBufMgr->surf_list, item_link) {
1638 tbm_surface_internal_dump_buffer(surface, "dump_all");
1641 tbm_surface_internal_dump_end();
1643 pthread_mutex_unlock(&gLock);
1648 /* internal function */
1650 _tbm_bufmgr_get_bufmgr(void)
1656 _tbm_bo_set_surface(tbm_bo bo, tbm_surface_h surface)
1658 _tbm_bufmgr_mutex_lock();
1660 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1661 TBM_BUFMGR_RETURN_VAL_IF_FAIL(_tbm_bo_is_valid(bo), 0);
1663 bo->surface = surface;
1665 _tbm_bufmgr_mutex_unlock();
1671 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *NativeDisplay)
1675 _tbm_bufmgr_mutex_lock();
1677 TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
1679 if (!bufmgr->backend->bufmgr_bind_native_display) {
1680 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1681 _tbm_bufmgr_mutex_unlock();
1685 ret = bufmgr->backend->bufmgr_bind_native_display(bufmgr, NativeDisplay);
1687 TBM_TRACE("error: tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1688 _tbm_bufmgr_mutex_unlock();
1692 TBM_TRACE("tbm_bufmgr(%p) NativeDisplay(%p)\n", bufmgr, NativeDisplay);
1694 _tbm_bufmgr_mutex_unlock();
1698 /* LCOV_EXCL_STOP */