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} };
370 for (i = 1; i < r->argc; i++) {
371 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
373 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
376 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_snapshot\n", r->argv[2]);
377 _wayland_tbm_monitor_server_usage(r);
382 _waylend_tbm_util_dump_snapshot(r->tbm_srv->bufmgr, scale);
383 _wayland_tbm_monitor_request_printf(r, "server: snapshot dump is done\n");
385 _send_request_to_client_with_wait(r, &target, 1);
389 _waylend_tbm_monitor_server_dump_queue(struct wayland_tbm_monitore_request *r)
391 struct wayland_tbm_monitor_target target = {.all = 1, .server = 1, .pid = {0} };
392 WL_TBM_MONITOR_PROC_STATE cmd;
397 cmd = _waylend_tbm_util_proc_state_parse(r->argv[1]);
398 if (cmd == WL_TBM_MONITOR_PROC_STATE_UNKNOWN) {
399 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown command for -dump_queue\n", r->argv[1]);
400 _wayland_tbm_monitor_server_usage(r);
404 for (i = 2; i < r->argc; i++) {
405 if (_waylend_tbm_util_target_parse(r->argv[i], &target))
407 if (_waylend_tbm_util_scale_parse(r->argv[i], &scale))
410 _wayland_tbm_monitor_request_printf(r, "'%s' - unknown target or scale for -dump_queue\n", r->argv[2]);
411 _wayland_tbm_monitor_server_usage(r);
416 st = _waylend_tbm_util_dump_queue(cmd, r->tbm_srv->bufmgr, scale);
417 _wayland_tbm_monitor_request_printf(r, "server: queue dump state: %s\n", st ? "on" : "off");
419 _send_request_to_client_with_wait(r, &target, 1);
424 void (*func)(struct wayland_tbm_monitore_request *r);
431 _waylend_tbm_monitor_server_list,
432 "get list of tbm clients",
438 _waylend_tbm_monitor_server_show,
439 "print all tbm_bo information for (all | server,<pid>,... ) to path (console | dlog | <filepath>)"
441 "<target> [<path>]\n"
443 "\t\t"" all - clients and server\n"
444 "\t\t"" server,<pid>,... - list of targets\n"
446 "1,2,server dlog,console; server tmp.txt; all"
450 _waylend_tbm_monitor_server_trace,
451 "trace the changes or the information of the tbm_bo (command: on | off | status)"
454 "\t\t"" on | off - turn on/off the trace\n"
455 "\t\t"" status - show status of all targets\n"
457 "\t\t"" all - clients and server(by default)\n"
458 "\t\t"" server,<pid>,... - list of targets\n"
460 "on server,1,2; off;"
464 _waylend_tbm_monitor_server_dump_snapshot,
465 "make dumps of all tbm_surfaces for (all | server,<pid>,... ) with scale"
469 "all scale=0.5; server,1,2 scale=0.5"
473 _waylend_tbm_monitor_server_dump_queue,
474 "make dumps for the tbm_surfaces which are queued with scale"
476 "<cmd> [<target>] [<scale>]\n"
478 "\t\t"" on - turn on the dump with scale\n"
479 "\t\t"" off - turn off the dump\n"
480 "\t\t"" status - show status of all targets\n"
482 "\t\t"" all - clients and server(by default)\n"
483 "\t\t"" server,<pid>,... - list of targets\n"
490 _wayland_tbm_monitor_server_usage(struct wayland_tbm_monitore_request *r)
492 int opt_size = sizeof(option_proc) / sizeof(option_proc[0]);
495 _wayland_tbm_monitor_request_printf(r, "usage: %s \n\n", r->app_name);
497 for (i = 0; i < opt_size; i++) {
499 _wayland_tbm_monitor_request_printf(r, "\t-%s\t%s\n", option_proc[i].opt, option_proc[i].desc);
500 if (option_proc[i].arg)
501 _wayland_tbm_monitor_request_printf(r, "\t\t %s\n", option_proc[i].arg);
502 if (option_proc[i].ex)
503 _wayland_tbm_monitor_request_printf(r, "\t\t ex) %s\n", option_proc[i].ex);
504 _wayland_tbm_monitor_request_printf(r, "\n");
508 static struct wayland_tbm_monitore_request *
509 _wayland_tbm_monitor_request_create(struct wl_client *client,
510 struct wl_resource *resource, const char *options)
516 static int id_count = 1;
518 struct wayland_tbm_monitore_request *r = calloc(1, sizeof(struct wayland_tbm_monitore_request));
519 memset(r, 0 , sizeof(struct wayland_tbm_monitore_request));
521 struct wayland_tbm_server *tbm_srv =
522 (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
524 /* copy options to a local memory */
525 snprintf(r->options, sizeof(r->options), "%s", options);
526 snprintf(r->arg_mem, sizeof(r->arg_mem), "%s", options);
528 r->wl_client = client;
529 r->wl_resource = resource;
531 r->len = WL_TBM_MONITOR_REPLY_MSG_LEN;
532 r->tbm_srv = tbm_srv;
535 wl_list_init(&r->link);
538 wl_client_get_credentials(r->wl_client, &pid, NULL, NULL);
539 _wayland_tbm_util_get_appname_from_pid(pid, r->app_name);
540 _wayland_tbm_util_get_appname_brief(r->app_name);
542 /* get access to the console of a wayland-tbm-monitor application */
543 snprintf(path, sizeof(path), "/proc/%d/fd/1", pid);
544 r->console = fopen(path, "a");
546 _wayland_tbm_monitor_request_printf(r, "Can't get access to the console\n");
550 /* get cwd of the client */
551 snprintf(path, sizeof(path), "/proc/%d/cwd", pid);
552 if (readlink(path, r->cwd, sizeof(r->cwd)) < 0) {
553 _wayland_tbm_monitor_request_printf(r, "Can't get cwd\n");
558 r->argv[r->argc] = strtok_r(r->arg_mem, " ", &end);
559 while (r->argv[r->argc]) {
561 if (r->argc == WL_TBM_MONITOR_ARGS_MAX) {
562 _wayland_tbm_monitor_request_printf(r, "Too many arguments\n");
566 r->argv[r->argc] = strtok_r(NULL, " ", &end);
569 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]);
573 for (i = 0; i < sizeof(option_proc) / sizeof(option_proc[0]); i++) {
574 if (r->argv[0][0] == '-' && !strncmp(r->argv[0] + 1, option_proc[i].opt, 32)) {
575 if (option_proc[i].func) {
576 wl_list_insert(&tbm_srv->tbm_monitor_request_list, &r->link);
577 option_proc[i].func(r);
579 _wayland_tbm_monitor_request_printf(r, "'%s' not implemented\n", r->argv[0]);
587 _wayland_tbm_monitor_request_printf(r, "'%s' is unknown options\n", r->argv[0]);
588 _wayland_tbm_monitor_server_usage(r);
593 struct wayland_tbm_monitore_request *
594 _wayland_tbm_monitor_get_request_by_id(struct wayland_tbm_server *tbm_srv, const char *id_str)
596 struct wayland_tbm_monitore_request *r = NULL;
599 if (sscanf(id_str, "%d", &id) != 1)
602 wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
609 struct wayland_tbm_monitore_request *
610 _wayland_tbm_monitor_get_request_by_resource(struct wayland_tbm_server *tbm_srv,
611 struct wl_resource *resource)
613 struct wayland_tbm_monitore_request *r = NULL;
614 wl_list_for_each(r, &tbm_srv->tbm_monitor_request_list, link)
615 if (r->wl_resource == resource)
622 _wayland_tbm_monitor_impl_responce_to_server(struct wl_client *client,
623 struct wl_resource *resource,
624 const char *message, const char *request_id)
626 struct wayland_tbm_monitore_request *r = NULL;
627 struct wayland_tbm_server *tbm_srv = NULL;
629 tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(resource);
630 r = _wayland_tbm_monitor_get_request_by_id(tbm_srv, request_id);
634 _wayland_tbm_monitor_request_printf(r, "%s", message);
635 _wayland_tbm_monitor_request_unref(r);
639 _wayland_tbm_monitor_impl_request_to_sever(struct wl_client *client,
640 struct wl_resource *resource,
643 struct wayland_tbm_monitore_request *r = NULL;
646 wl_client_get_credentials(client, NULL, &uid, NULL);
648 wl_tbm_monitor_send_done(resource, "wayland-tbm-monitor: SHOULD be a superuser.\n");
652 r = _wayland_tbm_monitor_request_create(client, resource, options);
653 if (r->wait_count == 0) {
654 wl_tbm_monitor_send_done(r->wl_resource, r->msg);
655 _wayland_tbm_monitor_request_delete(r);
660 _wayland_tbm_monitor_impl_destroy(struct wl_client *client,
661 struct wl_resource *wl_tbm_monitor)
666 wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
667 WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
670 wl_resource_destroy(wl_tbm_monitor);
674 _wayland_tbm_monitor_destroy_resource(struct wl_resource *wl_tbm_monitor)
676 struct wayland_tbm_monitore_request *r = NULL;
677 struct wayland_tbm_server *tbm_srv = NULL;
682 wl_client_get_credentials(wl_resource_get_client(wl_tbm_monitor), &pid, NULL, NULL);
683 WL_TBM_TRACE("wl_tbm_monitor destroy. client=%d\n", pid);
686 /* delete all requests from this client */
687 tbm_srv = (struct wayland_tbm_server *)wl_resource_get_user_data(wl_tbm_monitor);
688 while ((r = _wayland_tbm_monitor_get_request_by_resource(tbm_srv, wl_tbm_monitor)) != NULL)
689 _wayland_tbm_monitor_request_delete(r);
691 wl_list_remove(wl_resource_get_link(wl_tbm_monitor));
694 static const struct wl_tbm_monitor_interface _wayland_tbm_monitor_implementation = {
695 _wayland_tbm_monitor_impl_destroy,
696 _wayland_tbm_monitor_impl_request_to_sever,
697 _wayland_tbm_monitor_impl_responce_to_server,
701 _wayland_tbm_monitor_bind_cb(struct wl_client *client, void *data,
702 uint32_t version, uint32_t id)
704 struct wayland_tbm_server *tbm_srv = (struct wayland_tbm_server*)data;
705 struct wl_resource *wl_tbm_monitor;
707 wl_tbm_monitor = wl_resource_create(client, &wl_tbm_monitor_interface, 2, id);
708 if (!wl_tbm_monitor) {
709 wl_client_post_no_memory(client);
713 wl_resource_set_implementation(wl_tbm_monitor,
714 &_wayland_tbm_monitor_implementation,
716 _wayland_tbm_monitor_destroy_resource);
717 wl_list_insert(&tbm_srv->tbm_monitor_list, wl_resource_get_link(wl_tbm_monitor));
722 wl_client_get_credentials(client, &pid, NULL, NULL);
723 WL_TBM_TRACE("wl_tbm_monitor bind. client=%d\n", pid);
727 int wayland_tbm_monitor_server_init(struct wayland_tbm_server *tbm_srv)
729 tbm_srv->wl_tbm_monitor_global = wl_global_create(tbm_srv->display,
730 &wl_tbm_monitor_interface, 1, tbm_srv,
731 _wayland_tbm_monitor_bind_cb);
732 WL_TBM_RETURN_VAL_IF_FAIL(tbm_srv->wl_tbm_monitor_global, 0);
733 wl_list_init(&tbm_srv->tbm_monitor_list);
734 wl_list_init(&tbm_srv->tbm_monitor_request_list);