2 Copyright (C) 2015 Samsung Electronics co., Ltd. All Rights Reserved.
5 SooChan Lim <sc1.lim@samsung.com>,
6 Sangjin Lee <lsj119@samsung.com>,
7 Boram Park <boram1288.park@samsung.com>,
8 Changyeon Lee <cyeon.lee@samsung.com>
9 Roman Marchenko <r.marchenko@samsung.com>
11 Permission is hereby granted, free of charge, to any person obtaining a
12 copy of this software and associated documentation files (the "Software"),
13 to deal in the Software without restriction, including without limitation
14 the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 and/or sell copies of the Software, and to permit persons to whom the
16 Software is furnished to do so, subject to the following conditions:
18 The above copyright notice and this permission notice (including the next
19 paragraph) shall be included in all copies or substantial portions of the
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
42 #include <sys/types.h>
45 #include <tbm_surface.h>
46 #include <tbm_surface_internal.h>
47 #include <wayland-server.h>
49 #include "wayland-tbm-server-protocol.h"
51 #include "wayland-tbm-int.h"
52 #include "wayland-tbm-server.h"
54 struct wayland_tbm_monitore_request {
60 struct wayland_tbm_server *tbm_srv;
61 struct wl_client *wl_client;
62 struct wl_resource *wl_resource;
64 char cwd[WL_TBM_MONITOR_PATH_LEN];
66 char options[256]; /* raw options */
67 char arg_mem[256]; /* memory for argv */
68 char *argv[WL_TBM_MONITOR_ARGS_MAX];
72 char msg[WL_TBM_MONITOR_REPLY_MSG_LEN];
77 struct wayland_tbm_monitor_path path;
84 #define WL_TBM_TRACE(fmt, ...) if (bTrace) WL_TBM_S_LOG(fmt, ##__VA_ARGS__)
86 #define WL_TBM_TRACE(fmt, ...)
89 static void _wayland_tbm_monitor_server_usage(struct wayland_tbm_monitore_request *r);
92 _wayland_tbm_monitor_server_collect_files(FILE* f_to_collect, int need_remove)
99 char * dir_name = "/tmp/";
103 char *file_name = NULL;
105 dir_stream = opendir(dir_name);
107 WL_TBM_LOG("got an error trying to call 'opendir'.\n");
111 while ((entry = readdir(dir_stream))) {
112 if (strncmp(entry->d_name, "tbm_debug_show_", strlen("tbm_debug_show_")))
115 int tmp = asprintf(&file_name, "%s/%s", dir_name, entry->d_name);
119 fd = open(file_name, O_RDONLY);
121 WL_TBM_LOG(" got an error trying to open file");
126 while ((buf_len = read(fd, buf, sizeof(buf))) > 0)
127 fwrite(buf, buf_len, 1, f_to_collect);
137 closedir(dir_stream);
143 _wayland_tbm_monitor_add_info_printf(struct wayland_tbm_monitore_request *r)
146 if (r->path.file[0] != '\0') {
147 if ((f = fopen(r->path.file, "a+")) != NULL) {
148 _wayland_tbm_monitor_server_collect_files(f, r->path.console && r->console ? 0 : 1);
153 if (r->path.console && r->console)
154 _wayland_tbm_monitor_server_collect_files(r->console, 1);
158 _wayland_tbm_monitor_request_printf(struct wayland_tbm_monitore_request *r, const char *fmt, ...)
165 if (r->path.file[0] != '\0') {
166 if ((f = fopen(r->path.file, "a+")) != NULL) {
167 vfprintf(f, fmt, arg);
170 _wayland_tbm_monitor_request_printf(r, "server: can't write show to file: '%s'\n",
174 if (r->path.console && r->console)
175 vfprintf(r->console, fmt, arg);
180 _wayland_tbm_monitor_request_delete(struct wayland_tbm_monitore_request *r)
182 WL_TBM_TRACE("request_id:%d\n", r->id);
183 wl_list_remove(&r->link);
190 _wayland_tbm_monitor_request_unref(struct wayland_tbm_monitore_request *r)
193 WL_TBM_TRACE("request_id:%d wait_count:%d\n", r->id, r->wait_count);
194 if (r->wait_count <= 0) {
195 /* print additional info from clients */
196 _wayland_tbm_monitor_add_info_printf(r);
197 wl_tbm_monitor_send_done(r->wl_resource, r->msg);
198 _wayland_tbm_monitor_request_delete(r);
203 _send_request_to_client_with_wait(struct wayland_tbm_monitore_request *r,
204 struct wayland_tbm_monitor_target *target, int wait_answer)
207 struct wl_resource *c_res_tmp = NULL;
208 struct wl_resource *c_res = NULL;
212 snprintf(request_id, sizeof(request_id), "%d", r->id);
214 if (target->all) { /* send option string to all clients */
215 wl_resource_for_each(c_res, &r->tbm_srv->tbm_monitor_list) {
216 if (c_res == r->wl_resource)
219 wl_client_get_credentials(wl_resource_get_client(c_res), &c_pid, NULL, NULL);
220 WL_TBM_TRACE("send request:%d(%d) to client:%d option:'%s'\n", r->id, r->wait_count, c_pid, r->options);
222 wl_tbm_monitor_send_request_to_client(c_res, r->options, request_id);
227 while (target->pid[i]) {
229 t_pid = target->pid[i++];
230 /* find client and store into c_res */
231 wl_resource_for_each(c_res_tmp, &r->tbm_srv->tbm_monitor_list) {
232 if (c_res_tmp == r->wl_resource)
234 wl_client_get_credentials(wl_resource_get_client(c_res_tmp), &c_pid, NULL, NULL);
235 if (t_pid == c_pid) {
241 /* send option string to c_res */
243 WL_TBM_TRACE("send request:%d(%d) to client:%d option:'%s'\n", r->id, r->wait_count, t_pid, r->options);
244 wl_tbm_monitor_send_request_to_client(c_res, r->options, request_id);
248 _wayland_tbm_monitor_request_printf(r, "There isn't client with pid=%d\n", t_pid);
254 _waylend_tbm_monitor_server_list(struct wayland_tbm_monitore_request *r)
256 struct wl_resource *c_res = NULL;
257 struct wl_client *wl_client;
262 _wayland_tbm_monitor_request_printf(r, "================== app list =======================\n");
263 _wayland_tbm_monitor_request_printf(r, "no pid app_name\n");
265 if (!wl_list_empty(&r->tbm_srv->tbm_monitor_list)) {
266 wl_resource_for_each(c_res, &r->tbm_srv->tbm_monitor_list) {
268 wl_client = wl_resource_get_client(c_res);
269 wl_client_get_credentials(wl_client, &c_pid, NULL, NULL);
271 if (wl_client == r->wl_client)
274 _wayland_tbm_util_get_appname_from_pid(c_pid, app_name);
275 _wayland_tbm_util_get_appname_brief(app_name);
277 _wayland_tbm_monitor_request_printf(r, "%-3d%-5d%s\n", ++i, c_pid, app_name);
281 _wayland_tbm_monitor_request_printf(r, "======================================================\n");
285 _waylend_tbm_monitor_server_show(struct wayland_tbm_monitore_request *r)
287 struct wayland_tbm_monitor_target target = {0};
289 if (!_waylend_tbm_util_target_parse(r->argv[1], &target)) {
290 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target for -show\n", r->argv[1]);
295 r->path.console = r->path.dlog = r->path.file[0] = 0;
296 if (!_wayland_tbm_util_show_path_parse(r->argv[2], r->cwd, &r->path)) {
298 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown path for -show\n", r->argv[2]);
305 tbm_bufmgr_debug_show(r->tbm_srv->bufmgr);
309 show_str = tbm_bufmgr_debug_tbm_info_get(r->tbm_srv->bufmgr);
310 WL_TBM_RETURN_IF_FAIL(show_str);
312 if (r->path.console && r->console)
313 fprintf(r->console, "%s", show_str);
315 if (r->path.file[0] != '\0') {
318 if ((f = fopen(r->path.file, "a+")) != NULL) {
319 fprintf(f, "%s", show_str);
322 _wayland_tbm_monitor_request_printf(r,
323 "server: can't write show to file: '%s'\n",
331 _send_request_to_client_with_wait(r, &target, 1);
335 _waylend_tbm_monitor_server_trace(struct wayland_tbm_monitore_request *r)
338 struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
339 WL_TBM_MONITOR_PROC_STATE cmd;
342 cmd = _waylend_tbm_util_proc_state_parse(r->argv[1]);
344 if (cmd == WL_TBM_MONITOR_PROC_STATE_UNKNOWN) {
345 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown command for -trace\n", r->argv[1]);
346 _wayland_tbm_monitor_server_usage(r);
350 if (!_waylend_tbm_util_target_parse(r->argv[2], &target)) {
351 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target for -trace\n", r->argv[2]);
356 st = _waylend_tbm_util_trace(cmd, r->tbm_srv->bufmgr);
357 _wayland_tbm_monitor_request_printf(r, "server: trace state: %s\n", st ? "on" : "off");
360 _send_request_to_client_with_wait(r, &target, 1);
364 _waylend_tbm_monitor_server_dump_snapshot(struct wayland_tbm_monitore_request *r)
366 struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
371 for (i = 1; i < r->argc; i++) {
372 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
374 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
377 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_snapshot\n", r->argv[2]);
378 _wayland_tbm_monitor_server_usage(r);
383 path = _wayland_tbm_dump_directory_make();
384 _waylend_tbm_util_dump_snapshot(r->tbm_srv->bufmgr, scale, path);
385 _wayland_tbm_monitor_request_printf(r, "server: snapshot dump is done. path=%s\n", path);
388 _send_request_to_client_with_wait(r, &target, 1);
392 _waylend_tbm_monitor_server_dump_queue(struct wayland_tbm_monitore_request *r)
394 struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
395 WL_TBM_MONITOR_PROC_STATE cmd;
400 cmd = _waylend_tbm_util_proc_state_parse(r->argv[1]);
401 if (cmd == WL_TBM_MONITOR_PROC_STATE_UNKNOWN) {
402 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown command for -dump_queue\n", r->argv[1]);
403 _wayland_tbm_monitor_server_usage(r);
407 for (i = 2; i < r->argc; i++) {
408 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
410 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
413 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_queue\n", r->argv[2]);
414 _wayland_tbm_monitor_server_usage(r);
419 st = _waylend_tbm_util_dump_queue(cmd, r->tbm_srv->bufmgr, scale);
420 _wayland_tbm_monitor_request_printf(r, "server: queue dump state: %s\n", st ? "on" : "off");
422 _send_request_to_client_with_wait(r, &target, 1);
427 void (*func)(struct wayland_tbm_monitore_request *r);
434 _waylend_tbm_monitor_server_list,
435 "get list of tbm clients",
441 _waylend_tbm_monitor_server_show,
442 "print all tbm_bo information for (all | server,<pid>,... ) to path (console | dlog | <filepath>)"
444 "<target> [<path>]\n"
446 "\t\t"" all - clients and server\n"
447 "\t\t"" server,<pid>,... - list of targets\n"
449 "1,2,server dlog,console; server tmp.txt; all"
453 _waylend_tbm_monitor_server_trace,
454 "trace the changes or the information of the tbm_bo (command: on | off | status)"
457 "\t\t"" on | off - turn on/off the trace\n"
458 "\t\t"" status - show status of all targets\n"
460 "\t\t"" all - clients and server(by default)\n"
461 "\t\t"" server,<pid>,... - list of targets\n"
463 "on server,1,2; off;"
467 _waylend_tbm_monitor_server_dump_snapshot,
468 "make dumps of all tbm_surfaces for (all | server,<pid>,... ) with scale"
472 "all scale=0.5; server,1,2 scale=0.5"
476 _waylend_tbm_monitor_server_dump_queue,
477 "make dumps for the tbm_surfaces which are queued with scale"
479 "<cmd> [<target>] [<scale>]\n"
481 "\t\t"" on - turn on the dump with scale\n"
482 "\t\t"" off - turn off the dump\n"
483 "\t\t"" status - show status of all targets\n"
485 "\t\t"" all - clients and server(by default)\n"
486 "\t\t"" server,<pid>,... - list of targets\n"
493 _wayland_tbm_monitor_server_usage(struct wayland_tbm_monitore_request *r)
495 int opt_size = sizeof(option_proc) / sizeof(option_proc[0]);
498 _wayland_tbm_monitor_request_printf(r, "usage: %s \n\n", r->app_name);
500 for (i = 0; i < opt_size; i++) {
502 _wayland_tbm_monitor_request_printf(r, "\t-%s\t%s\n", option_proc[i].opt, option_proc[i].desc);
503 if (option_proc[i].arg)
504 _wayland_tbm_monitor_request_printf(r, "\t\t %s\n", option_proc[i].arg);
505 if (option_proc[i].ex)
506 _wayland_tbm_monitor_request_printf(r, "\t\t ex) %s\n", option_proc[i].ex);
507 _wayland_tbm_monitor_request_printf(r, "\n");
511 static struct wayland_tbm_monitore_request *
512 _wayland_tbm_monitor_request_create(struct wl_client *client,
513 struct wl_resource *resource, const char *options)
519 static int id_count = 1;
521 struct wayland_tbm_monitore_request *r = calloc(1, sizeof(struct wayland_tbm_monitore_request));
522 memset(r, 0 , sizeof(struct wayland_tbm_monitore_request));
524 struct wayland_tbm_server *tbm_srv =
525 (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
527 /* copy options to a local memory */
528 snprintf(r->options, sizeof(r->options), "%s", options);
529 snprintf(r->arg_mem, sizeof(r->arg_mem), "%s", options);
531 r->wl_client = client;
532 r->wl_resource = resource;
534 r->len = WL_TBM_MONITOR_REPLY_MSG_LEN;
535 r->tbm_srv = tbm_srv;
538 wl_list_init(&r->link);
541 wl_client_get_credentials(r->wl_client, &pid, NULL, NULL);
542 _wayland_tbm_util_get_appname_from_pid(pid, r->app_name);
543 _wayland_tbm_util_get_appname_brief(r->app_name);
545 /* get access to the console of a wayland-tbm-monitor application */
546 snprintf(path, sizeof(path), "/proc/%d/fd/1", pid);
547 r->console = fopen(path, "a");
549 _wayland_tbm_monitor_request_printf(r, "Can't get access to the console\n");
553 /* get cwd of the client */
554 snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
555 if (readlink(path, r->cwd, sizeof(r->cwd)) < 0) {
556 _wayland_tbm_monitor_request_printf(r, "Can't get cwd\n");
561 r->argv[r->argc] = strtok_r(r->arg_mem, " ", &end);
562 while (r->argv[r->argc]) {
564 if (r->argc == WL_TBM_MONITOR_ARGS_MAX) {
565 _wayland_tbm_monitor_request_printf(r, "Too many arguments\n");
569 r->argv[r->argc] = strtok_r(NULL, " ", &end);
572 WL_TBM_TRACE("request_id:%d option:'%s' argc:%d [%s %s %s] \n", r->id, r->options, r->argc, r->argv[0], r->argv[1], r->argv[2]);
576 for (i = 0; i < sizeof(option_proc) / sizeof(option_proc[0]); i++) {
577 if (r->argv[0][0] == '-' && !strncmp(r->argv[0] + 1, option_proc[i].opt, 32)) {
578 if (option_proc[i].func) {
579 wl_list_insert(&tbm_srv->tbm_monitor_request_list, &r->link);
580 option_proc[i].func(r);
582 _wayland_tbm_monitor_request_printf(r, "'%s' not implemented\n", r->argv[0]);
590 _wayland_tbm_monitor_request_printf(r, "'%s' is unknown options\n", r->argv[0]);
591 _wayland_tbm_monitor_server_usage(r);
596 struct wayland_tbm_monitore_request *
597 _wayland_tbm_monitor_get_request_by_id(struct wayland_tbm_server *tbm_srv, const char *id_str)
599 struct wayland_tbm_monitore_request *r = NULL;
602 if (sscanf(id_str, "%d", &id) != 1)
605 wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
612 struct wayland_tbm_monitore_request *
613 _wayland_tbm_monitor_get_request_by_resource(struct wayland_tbm_server *tbm_srv,
614 struct wl_resource *resource)
616 struct wayland_tbm_monitore_request *r = NULL;
617 wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
618 if (r->wl_resource == resource)
625 _wayland_tbm_monitor_impl_responce_to_server(struct wl_client *client,
626 struct wl_resource *resource,
627 const char *message, const char *request_id)
629 struct wayland_tbm_monitore_request *r = NULL;
630 struct wayland_tbm_server *tbm_srv = NULL;
632 tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
633 r = _wayland_tbm_monitor_get_request_by_id(tbm_srv, request_id);
637 _wayland_tbm_monitor_request_printf(r, "%s", message);
638 _wayland_tbm_monitor_request_unref(r);
642 _wayland_tbm_monitor_impl_request_to_sever(struct wl_client *client,
643 struct wl_resource *resource,
646 struct wayland_tbm_monitore_request *r = NULL;
649 wl_client_get_credentials(client, NULL, &uid, NULL);
651 wl_tbm_monitor_send_done(resource, "wayland-tbm-monitor: SHOULD be a superuser.\n");
655 r = _wayland_tbm_monitor_request_create(client, resource, options);
656 if (r->wait_count == 0) {
657 wl_tbm_monitor_send_done(r->wl_resource, r->msg);
658 _wayland_tbm_monitor_request_delete(r);
663 _wayland_tbm_monitor_impl_destroy(struct wl_client *client,
664 struct wl_resource *wl_tbm_monitor)
669 wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
670 WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
673 wl_resource_destroy(wl_tbm_monitor);
677 _wayland_tbm_monitor_destroy_resource(struct wl_resource *wl_tbm_monitor)
679 struct wayland_tbm_monitore_request *r = NULL;
680 struct wayland_tbm_server *tbm_srv = NULL;
685 wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
686 WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
689 /* delete all requests from this client */
690 tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(wl_tbm_monitor);
691 while ((r = _wayland_tbm_monitor_get_request_by_resource(tbm_srv, wl_tbm_monitor)) != NULL)
692 _wayland_tbm_monitor_request_delete(r);
694 wl_list_remove(wl_resource_get_link(wl_tbm_monitor));
697 static const struct wl_tbm_monitor_interface _wayland_tbm_monitor_implementation = {
698 _wayland_tbm_monitor_impl_destroy,
699 _wayland_tbm_monitor_impl_request_to_sever,
700 _wayland_tbm_monitor_impl_responce_to_server,
704 _wayland_tbm_monitor_bind_cb(struct wl_client *client, void *data,
705 uint32_t version, uint32_t id)
707 struct wayland_tbm_server *tbm_srv = (struct wayland_tbm_server*)data;
708 struct wl_resource *wl_tbm_monitor;
710 wl_tbm_monitor = wl_resource_create(client, &wl_tbm_monitor_interface, 2, id);
711 if (!wl_tbm_monitor) {
712 wl_client_post_no_memory(client);
716 wl_resource_set_implementation(wl_tbm_monitor,
717 &_wayland_tbm_monitor_implementation,
719 _wayland_tbm_monitor_destroy_resource);
720 wl_list_insert(&tbm_srv->tbm_monitor_list, wl_resource_get_link(wl_tbm_monitor));
725 wl_client_get_credentials(client, &pid, NULL, NULL);
726 WL_TBM_TRACE("wl_tbm_monitor bind. client=%d\n", pid);
730 int wayland_tbm_monitor_server_init(struct wayland_tbm_server *tbm_srv)
732 tbm_srv->wl_tbm_monitor_global = wl_global_create(tbm_srv->display,
733 &wl_tbm_monitor_interface, 1, tbm_srv,
734 _wayland_tbm_monitor_bind_cb);
735 WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv->wl_tbm_monitor_global, 0);
736 wl_list_init(&tbm_srv->tbm_monitor_list);
737 wl_list_init(&tbm_srv->tbm_monitor_request_list);