/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
* Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
#include <linux/string.h>
-#include <uprobe/swap_uaccess.h>
#include <us_manager/sspt/sspt.h>
#include <us_manager/probes/probe_info_new.h>
#include "wsp.h"
#include "wsp_res.h"
#include "wsp_msg.h"
-
struct wsp_probe {
const char *name;
struct probe_new probe;
struct wsp_probe *probe_array;
};
+static char *webapp_path;
+static char *chromium_path;
-static char *webapp_path = NULL;
-static char *ewebkit_path = NULL;
-
-
-#define WSP_PROBE_MAKE(__name, __desc) \
-{ \
- .name = __name, \
- .probe.offset = 0, \
- .probe.desc = __desc \
-}
-
-
-static void do_res_processing_begin(void *data, void *ptr, enum wsp_res_t type)
-{
- struct wsp_res **save_res = (struct wsp_res **)data;
- struct wsp_res *res;
-
- res = wsp_res_find(ptr, type);
-
- /* save res pointer */
- *save_res = res;
- if (res) {
- wsp_msg(WSP_RES_PROC_BEGIN, res->id, NULL);
- wsp_res_stat_set_next(res, WRS_ADD_DATA);
- }
-}
-
-static void do_res_processing_end(struct wsp_res *res)
-{
- wsp_msg(WSP_RES_PROC_END, res->id, NULL);
-}
-
-static void do_res_finish(struct wsp_res *res)
-{
- wsp_msg(WSP_RES_LOAD_END, res->id, NULL);
- wsp_res_stat_set_next(res, WRS_FINISH);
- wsp_res_del(res);
-}
-
-
-/*
- * soup_req
- */
-static int soup_req_handle(struct uprobe *p, struct pt_regs *regs)
-{
- enum { max_str_len = 512 };
- const char __user *user_s;
- const char *path;
- struct wsp_res *res;
-
- res = wsp_res_last();
- if (res == NULL) {
- pr_err("last wsp_res is not found\n");
- return 0;
- }
-
- user_s = (const char __user *)swap_get_uarg(regs, 1);
- path = strdup_from_user(user_s, GFP_ATOMIC);
- if (path == NULL) {
- pr_warn("soup_req_handle: invalid path\n");
- return 0;
- }
-
- wsp_msg(WSP_RES_LOAD_BEGIN, res->id, path);
- wsp_res_stat_set_next(res, WRS_SOUP_REQ);
- kfree(path);
-
- return 0;
+#define WSP_PROBE_MAKE(_name_, _offset_, _desc_) \
+{ \
+ .name = (_name_), \
+ .probe.offset = (_offset_), \
+ .probe.desc = (_desc_) \
}
-static struct probe_desc soup_req = MAKE_UPROBE(soup_req_handle);
-
-
-/*
- * main_res_req
- */
-static int mres_req_handle(struct uprobe *p, struct pt_regs *regs)
-{
- void *ptr = (void *)swap_get_uarg(regs, 0);
- struct wsp_res *res;
-
- res = wsp_res_new(ptr, WR_MAIN);
- if (res)
- wsp_res_stat_set_next(res, WRS_WILL_REQ);
-
- return 0;
-}
-
-static struct probe_desc mres_req = MAKE_UPROBE(mres_req_handle);
-
-
/*
- * main_res_add_data
+ * res_request
*/
+/* blink::ResourceLoader.m_request.m_url */
+#define URL_OFFSET 84
+/* base::String.m_impl.m_ptr */
+#define URL_LEN_OFFSET 4
+#define URL_DATA_OFFSET 12
-static int mres_adata_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
-{
- void *ptr = (void *)swap_get_uarg(regs, 0);
-
- do_res_processing_begin(ri->data, ptr, WR_MAIN);
-
- return 0;
-}
-
-static int mres_adata_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
+static char *path_get_from_object(unsigned long ptr)
{
- struct wsp_res *res = *(struct wsp_res **)ri->data;
-
- if (res)
- do_res_processing_end(res);
-
- return 0;
-}
-
-static struct probe_desc mres_adata =
- MAKE_URPROBE(mres_adata_eh, mres_adata_rh,
- sizeof(struct wsp_res *));
-
-
-/*
- * main_res_finish
- */
-static int mres_finish_handle(struct uprobe *p, struct pt_regs *regs)
-{
- void *ptr = (void *)swap_get_uarg(regs, 0);
- struct wsp_res *res;
-
- res = wsp_res_find(ptr, WR_MAIN);
- if (res) {
- wsp_current_set_stat(TDS_FINISH_MAIN_LOAD);
- do_res_finish(res);
+ char *path;
+ unsigned long url, len, ret;
+
+ get_user(url, (unsigned long __user *)(ptr + URL_OFFSET));
+ get_user(len, (unsigned long __user *)(url + URL_LEN_OFFSET));
+ path = kzalloc(len + 1, GFP_KERNEL);
+ if (!path)
+ return NULL;
+
+ ret = copy_from_user(path,
+ (const void __user *)(url + URL_DATA_OFFSET),
+ len);
+ if (ret) {
+ kfree(path);
+ path = NULL;
}
- return 0;
-}
-
-static struct probe_desc mres_finish = MAKE_UPROBE(mres_finish_handle);
+ path[len] = '\0';
+ return path;
+}
-/*
- * res_request
- */
static int res_request_handle(struct uprobe *p, struct pt_regs *regs)
{
- void *ptr = (void *)swap_get_uarg(regs, 0);
- struct wsp_res *res;
-
- res = wsp_res_last();
- if (res) {
- if (res->type == WR_MAIN && res->stat == WRS_WILL_REQ)
- /* skip */
- return 0;
+ unsigned long ptr;
+ char *path;
+
+ ptr = (unsigned long)swap_get_uarg(regs, 0);
+ path = path_get_from_object(ptr);
+ if (path) {
+ int id = wsp_resource_data_add(ptr, path);
+ if (id >= 0)
+ wsp_msg(WSP_RES_LOAD_BEGIN, id, path);
}
- res = wsp_res_new(ptr, WR_ANY);
- if (res)
- wsp_res_stat_set_next(res, WRS_WILL_REQ);
-
return 0;
}
static struct probe_desc res_request = MAKE_UPROBE(res_request_handle);
-
/*
* res_finish
*/
static int res_finish_ehandle(struct uretprobe_instance *ri,
struct pt_regs *regs)
{
- void *ptr = (void *)swap_get_uarg(regs, 0);
+ int id;
+ unsigned long ptr = (unsigned long)swap_get_uarg(regs, 0);
- do_res_processing_begin(ri->data, ptr, WR_ANY);
+ id = wsp_resource_data_id(ptr);
+ if (id >= 0) {
+ *(unsigned long *)ri->data = ptr;
+ wsp_msg(WSP_RES_PROC_BEGIN, id, NULL);
+ }
return 0;
}
static int res_finish_rhandle(struct uretprobe_instance *ri,
struct pt_regs *regs)
{
- struct wsp_res *res = *(struct wsp_res **)ri->data;
-
- if (res) {
- do_res_processing_end(res);
- do_res_finish(res);
+ int id;
+ unsigned long ptr;
+
+ ptr = *(unsigned long *)ri->data;
+ id = wsp_resource_data_id(ptr);
+ if (id >= 0) {
+ wsp_msg(WSP_RES_PROC_END, id, NULL);
+ wsp_msg(WSP_RES_LOAD_END, id, NULL);
+ wsp_resource_data_del(ptr);
}
return 0;
static struct probe_desc res_finish =
MAKE_URPROBE(res_finish_ehandle, res_finish_rhandle,
- sizeof(struct wsp_res *));
-
+ sizeof(unsigned long));
/*
* redraw
*/
static int redraw_eh(struct uretprobe_instance *ri, struct pt_regs *regs)
{
- enum tdata_stat stat;
-
- stat = wsp_current_get_stat();
-
- if (stat == TDS_FINISH_MAIN_LOAD)
- wsp_msg(WSP_DRAW_BEGIN, 0, NULL);
+ wsp_msg(WSP_DRAW_BEGIN, 0, NULL);
return 0;
}
static int redraw_rh(struct uretprobe_instance *ri, struct pt_regs *regs)
{
- if (wsp_current_get_stat() == TDS_FINISH_MAIN_LOAD) {
- wsp_current_set_stat(TDS_DRAW);
- wsp_msg(WSP_DRAW_END, 0, NULL);
- }
+ wsp_msg(WSP_DRAW_END, 0, NULL);
return 0;
}
static struct probe_desc redraw = MAKE_URPROBE(redraw_eh, redraw_rh, 0);
+/* blink::ResourceLoader::start() */
+#define RES_REQ "_ZN5blink14ResourceLoader5startEv"
+/* blink::ResourceLoader::didFinishLoading(WebURLLoader*, double , int64_t) */
+#define RES_FINISH "_ZN5blink14ResourceLoader16didFinishLoadingEPNS_12WebURLLoaderEdx"
-static struct wsp_probe ewebkit_probe_array[] = {
- /* plt */
- /* soup_requester_request@plt */
- WSP_PROBE_MAKE("soup_requester_request@plt", &soup_req),
-
- /* main_res */
- /* WebCore::MainResourceLoader::willSendRequest(WebCore::ResourceRequest&, WebCore::ResourceResponse const&) */
- WSP_PROBE_MAKE("_ZN7WebCore18MainResourceLoader15willSendRequestERNS_15ResourceRequestERKNS_16ResourceResponseE", &mres_req),
- /* WebCore::MainResourceLoader::addData(char const*, int, bool) */
- WSP_PROBE_MAKE("_ZN7WebCore18MainResourceLoader7addDataEPKcib", &mres_adata),
- /* WebCore::MainResourceLoader::didFinishLoading(double) */
- WSP_PROBE_MAKE("_ZN7WebCore18MainResourceLoader16didFinishLoadingEd", &mres_finish),
-
+/* content::RenderWidget::DidCommitAndDrawCompositorFrame */
+#define REDRAW "_ZN7content23CompositorOutputSurface11SwapBuffersEPN2cc15CompositorFrameE"
+static struct wsp_probe __probe_array[] = {
/* res */
- /* WebCore::ResourceLoader::willSendRequest(WebCore::ResourceRequest&, WebCore::ResourceResponse const&) */
- WSP_PROBE_MAKE("_ZN7WebCore14ResourceLoader15willSendRequestERNS_15ResourceRequestERKNS_16ResourceResponseE", &res_request),
- /* WebCore::ResourceLoader::didFinishLoading(WebCore::ResourceHandle*, double) */
- WSP_PROBE_MAKE("_ZN7WebCore14ResourceLoader16didFinishLoadingEPNS_14ResourceHandleEd", &res_finish),
-
+ WSP_PROBE_MAKE(RES_REQ, 0, &res_request),
+ WSP_PROBE_MAKE(RES_FINISH, 0, &res_finish),
/* redraw */
- /* WebKit::LayerTreeCoordinator::flushPendingLayerChanges() */
- WSP_PROBE_MAKE("_ZN6WebKit20LayerTreeCoordinator24flushPendingLayerChangesEv", &redraw),
+ WSP_PROBE_MAKE(REDRAW, 0, &redraw),
};
-enum {
- ewebkit_probes_cnt =
- sizeof(ewebkit_probe_array) / sizeof(struct wsp_probe)
-};
-
-static struct wsp_bin ewebkit = {
+static struct wsp_bin chromium_bin = {
.name = NULL,
- .cnt = ewebkit_probes_cnt,
- .probe_array = ewebkit_probe_array
+ .probe_array = __probe_array,
+ .cnt = ARRAY_SIZE(__probe_array)
};
-
-/* check ewebkit_probe_array on init address */
+/* check chromium_bin array on init address */
static bool wsp_is_addr_init(void)
{
int i;
- for (i = 0; i < ewebkit_probes_cnt; ++i)
- if (ewebkit_probe_array[i].probe.offset == 0)
+ for (i = 0; i < chromium_bin.cnt; ++i)
+ if (chromium_bin.probe_array[i].probe.offset == 0)
return false;
return true;
}
-
static int wsp_probe_register(struct pf_group *pfg, struct dentry *dentry,
struct wsp_probe *wsp_probe)
{
pin_unregister(probe_new, pfg, dentry);
}
-
-
-
static int wsp_bin_register(struct pf_group *pfg, struct wsp_bin *bin)
{
int i, ret;
struct dentry *dentry;
dentry = dentry_by_path(bin->name);
- if (dentry == NULL) {
+ if (!dentry) {
pr_err("dentry not found (path='%s'\n", bin->name);
return -EINVAL;
}
ret = wsp_probe_register(pfg, dentry, p);
if (ret) {
- pr_err("ERROR: wsp_probe_register, addr=%lx ret=%d\n",
+ pr_err("failed to register WSP probe (%lx:%d)\n",
p->probe.offset, ret);
return ret;
}
struct dentry *dentry;
dentry = dentry_by_path(bin->name);
- for (i = 0; i < bin->cnt; ++i)
- wsp_probe_unregister(pfg, dentry, &bin->probe_array[i]);
+ if (!dentry) {
+ pr_err("dentry not found (path='%s'\n", bin->name);
+ return;
+ }
+
+ for (i = 0; i < bin->cnt; ++i) {
+ struct wsp_probe *p = &bin->probe_array[i];
+
+ wsp_probe_unregister(pfg, dentry, p);
+ }
}
-static void do_set_path(char **dest, char *path, size_t len)
+static char *do_set_path(char *path, size_t len)
{
- *dest = kmalloc(len, GFP_KERNEL);
- if (*dest == NULL) {
- printk("Not enough memory to init path\n");
- return;
- }
+ char *p;
+
+ p = kmalloc(len, GFP_KERNEL);
+ if (!p)
+ return NULL;
- strncpy(*dest, path, len);
+ strncpy(p, path, len);
+ return p;
}
static void do_free_path(char **dest)
*dest = NULL;
}
-
static struct pf_group *g_pfg;
static int wsp_app_register(void)
{
struct dentry *dentry;
- if (webapp_path == NULL || ewebkit_path == NULL) {
- printk("WSP: some required paths are not set!\n");
+ if (!webapp_path || !chromium_path) {
+ pr_err("WSP: some required paths are not set!\n");
return -EINVAL;
}
- ewebkit.name = ewebkit_path;
+ chromium_bin.name = chromium_path;
dentry = dentry_by_path(webapp_path);
- if (dentry == NULL) {
+ if (!dentry) {
pr_err("dentry not found (path='%s'\n", webapp_path);
return -EINVAL;
}
g_pfg = get_pf_group_by_dentry(dentry, (void *)dentry);
- if (g_pfg == NULL) {
- pr_err("g_pfg is NULL (by dentry=%p)\n", dentry);
+ if (!g_pfg) {
+ pr_err("WSP: g_pfg is NULL (by dentry=%p)\n", dentry);
return -ENOMEM;
}
- return wsp_bin_register(g_pfg, &ewebkit);
+ return wsp_bin_register(g_pfg, &chromium_bin);
}
static void wsp_app_unregister(void)
{
- if (ewebkit.name == NULL) {
- printk("WSP: ewebkit path is not initialized\n");
+ if (!chromium_bin.name) {
+ pr_err("WSP: chromium path is not initialized\n");
return;
}
- wsp_bin_unregister(g_pfg, &ewebkit);
+ wsp_bin_unregister(g_pfg, &chromium_bin);
put_pf_group(g_pfg);
}
-
static int do_wsp_on(void)
{
int ret;
return ret;
}
-static void do_wsp_off(void)
+static int do_wsp_off(void)
{
wsp_app_unregister();
wsp_res_exit();
- do_free_path(&webapp_path);
- do_free_path(&ewebkit_path);
-}
+ return 0;
+}
static enum wsp_mode g_mode = WSP_OFF;
static DEFINE_MUTEX(g_mode_mutex);
if (mutex_trylock(&g_mode_mutex) == 0)
return -EBUSY;
- for (i = 0; i < ewebkit_probes_cnt; ++i) {
- if (0 == strcmp(name, ewebkit_probe_array[i].name)) {
- ewebkit_probe_array[i].probe.offset = offset;
+ for (i = 0; i < chromium_bin.cnt; ++i) {
+ if (!strcmp(name, chromium_bin.probe_array[i].name)) {
+ chromium_bin.probe_array[i].probe.offset = offset;
goto unlock;
}
}
int wsp_set_mode(enum wsp_mode mode)
{
- int ret = 0;
+ int ret = -EINVAL;
+
+ if (g_mode == mode)
+ return -EBUSY;
mutex_lock(&g_mode_mutex);
switch (mode) {
case WSP_ON:
- if (g_mode == WSP_ON) {
- ret = -EBUSY;
- goto unlock;
- }
-
ret = wsp_is_addr_init() ? do_wsp_on() : -EPERM;
break;
case WSP_OFF:
- if (g_mode == WSP_OFF) {
- ret = -EBUSY;
- goto unlock;
- }
-
- do_wsp_off();
- break;
- default:
- ret = -EINVAL;
+ ret = do_wsp_off();
break;
}
-unlock:
- if (ret == 0)
+ if (!ret)
g_mode = mode;
mutex_unlock(&g_mode_mutex);
void wsp_set_webapp_path(char *path, size_t len)
{
do_free_path(&webapp_path);
- do_set_path(&webapp_path, path, len);
+ webapp_path = do_set_path(path, len);
}
-void wsp_set_ewebkit_path(char *path, size_t len)
+void wsp_set_chromium_path(char *path, size_t len)
{
- do_free_path(&ewebkit_path);
- do_set_path(&ewebkit_path, path, len);
+ do_free_path(&chromium_path);
+ chromium_path = do_set_path(path, len);
}
int wsp_init(void)
void wsp_exit(void)
{
wsp_set_mode(WSP_OFF);
+ do_free_path(&webapp_path);
+ do_free_path(&chromium_path);
}
#define _WSP_H
/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
* Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
enum wsp_mode {
WSP_ON,
WSP_OFF
};
-
int wsp_set_addr(const char *name, unsigned long offset);
int wsp_set_mode(enum wsp_mode mode);
enum wsp_mode wsp_get_mode(void);
void wsp_set_webapp_path(char *path, size_t len);
-void wsp_set_ewebkit_path(char *path, size_t len);
+void wsp_set_chromium_path(char *path, size_t len);
int wsp_init(void);
void wsp_exit(void);
-
#endif /* _WSP_H */
/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
- * Copyright (C) Samsung Electronics, 2014
+ * Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
#include <linux/slab.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <master/swap_debugfs.h>
#include "wsp.h"
-
+#include "wsp_debugfs.h"
static int do_write_cmd(const char *buf, size_t count)
{
unsigned long offset;
name = kmalloc(count, GFP_KERNEL);
- if (name == NULL)
+ if (!name)
return -ENOMEM;
n = sscanf(buf, "%lx %1024s", &offset, name);
return -ENOMEM;
buf = kmalloc(count + 1, GFP_KERNEL);
- if (buf == NULL)
+ if (!buf)
return -ENOMEM;
if (copy_from_user(buf, user_buf, count)) {
.llseek = default_llseek,
};
-
-
-
/* ============================================================================
* === DEBUGFS FOR ENABLE ===
* ============================================================================
.llseek = default_llseek,
};
-
-
-
/* ============================================================================
* === DEBUGFS FOR WEBAPP_PATH ===
* ============================================================================
*/
-static ssize_t write_webapp_path(struct file *file, const char __user *user_buf,
- size_t len, loff_t *ppos)
+static ssize_t write_webapp_path(struct file *file,
+ const char __user *user_buf,
+ size_t len, loff_t *ppos)
{
ssize_t ret;
char *path;
path = kmalloc(len, GFP_KERNEL);
- if (path == NULL) {
+ if (!path) {
ret = -ENOMEM;
goto write_webapp_path_failed;
}
}
path[len - 1] = '\0';
-
wsp_set_webapp_path(path, len);
ret = len;
.write = write_webapp_path
};
-
-
-
/* ============================================================================
* === DEBUGFS FOR EWEBKIT_PATH ===
* ============================================================================
*/
-static ssize_t write_ewebkit_path(struct file *file, const char __user *user_buf,
- size_t len, loff_t *ppos)
+static ssize_t write_ewebkit_path(struct file *file,
+ const char __user *user_buf,
+ size_t len, loff_t *ppos)
{
ssize_t ret;
char *path;
path = kmalloc(len, GFP_KERNEL);
- if (path == NULL) {
+ if (!path) {
ret = -ENOMEM;
goto write_ewebkit_path_failed;
}
path[len - 1] = '\0';
- wsp_set_ewebkit_path(path, len);
+ wsp_set_chromium_path(path, len);
ret = len;
.write = write_ewebkit_path
};
-
-
-
static struct dentry *wsp_dir;
void wsp_debugfs_exit(void)
{
- if (wsp_dir)
- debugfs_remove_recursive(wsp_dir);
-
+ debugfs_remove_recursive(wsp_dir);
wsp_dir = NULL;
}
struct dentry *dentry;
dentry = swap_debugfs_getdir();
- if (dentry == NULL)
+ if (!dentry)
return -ENOENT;
wsp_dir = debugfs_create_dir("wsp", dentry);
- if (wsp_dir == NULL)
+ if (!wsp_dir)
return -ENOMEM;
dentry = debugfs_create_file("enabled", 0600, wsp_dir, NULL,
&fops_enabled);
- if (dentry == NULL)
+ if (!dentry)
goto fail;
dentry = debugfs_create_file("cmd", 0600, wsp_dir, NULL, &fops_cmd);
- if (dentry == NULL)
+ if (!dentry)
goto fail;
dentry = debugfs_create_file("webapp_path", 0600, wsp_dir, NULL,
&fops_webapp_path);
- if (dentry == NULL)
+ if (!dentry)
goto fail;
dentry = debugfs_create_file("ewebkit_path", 0600, wsp_dir, NULL,
&fops_ewebkit_path);
- if (dentry == NULL)
+ if (!dentry)
goto fail;
return 0;
#define _WSP_DEBUGFS_H
/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
- * Copyright (C) Samsung Electronics, 2014
+ * Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
int wsp_debugfs_init(void);
void wsp_debugfs_exit(void);
-
#endif /* _WSP_DEBUGFS_H */
/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
- * Copyright (C) Samsung Electronics, 2014
+ * Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
#include <master/swap_initializer.h>
#include "wsp.h"
#include "wsp_debugfs.h"
-
SWAP_LIGHT_INIT_MODULE(NULL, wsp_init, wsp_exit,
wsp_debugfs_init, wsp_debugfs_exit);
/*
+ * wsp/wsp_msg.c
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
- * Copyright (C) Samsung Electronics, 2016
+ * Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
#include <linux/sched.h>
#include <linux/string.h>
#include <writer/swap_msg.h>
#include "wsp_msg.h"
-
/*
* MSG_WSP (payload):
* +-------------+----------+----------+
- * | name | type | lenght |
+ * | name | type | length |
* +-------------+----------+----------+
* | PID | int | 4 |
* | wsp_id | int | 4 |
*
* 1. WSP_RES_LOAD_BEGIN:
* +--------+--------+----------+
- * | name | type | lenght |
+ * | name | type | length |
* +--------+--------+----------+
* | res_id | int | 4 |
* | path | string | variable |
*
* 2. WSP_RES_LOAD_END, WSP_RES_PROC_BEGIN, WSP_RES_PROC_END:
* +--------+--------+----------+
- * | name | type | lenght |
+ * | name | type | length |
* +--------+--------+----------+
* | res_id | int | 4 |
* +--------+--------+----------+
break;
default:
- printk(KERN_ERR "unknown wsp_id: id=%u\n", (unsigned)id);
+ pr_err("unknown wsp_id: id=%u\n", (unsigned int)id);
return -EINVAL;
}
size = swap_msg_size(m);
ret = pack_wsp_msg(data, size, id, res_id, path);
if (ret < 0) {
- printk(KERN_ERR "error MSG_WSP packing, ret=%d\n", ret);
+ pr_err("error MSG_WSP packing, ret=%d\n", ret);
goto put_msg;
}
#define _WSP_MSG_H
/*
+ * wsp/wsp_msg.h
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
* Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
#include <linux/types.h>
-
enum wsp_id {
WSP_RES_LOAD_BEGIN = 0x0001,
WSP_RES_LOAD_END = 0x0002,
WSP_DRAW_END = 0x0006
};
-
void wsp_msg(enum wsp_id id, u32 res_id, const char *path);
-
#endif /* _WSP_MSG_H */
/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
- * Copyright (C) Samsung Electronics, 2016
+ * Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
#include <linux/slab.h>
#include <linux/atomic.h>
#include <kprobe/swap_kprobes_deps.h>
#include "wsp_res.h"
-static atomic_t wsp_res_count;
+static atomic_t __resource_id = ATOMIC_INIT(0);
-static int wsp_tdata_get_id(void)
+static inline int __wsp_resource_id(void)
{
- return atomic_inc_return(&wsp_res_count);
+ return atomic_inc_return(&__resource_id);
}
-static struct wsp_tdata *g_tdata;
-
-/* FIXME: get_tdata() need receive for each processes */
-static struct wsp_tdata *get_tdata(void)
-{
- return g_tdata;
-}
-
-
-
-
-
-/* ============================================================================
- * = wsp_tdata =
- * ============================================================================
- */
-struct wsp_tdata {
- struct list_head res_list;
- spinlock_t lock;
-
- enum tdata_stat stat;
+struct wsp_resource_data {
+ struct list_head list;
+ int id;
+ unsigned long addr;
+ char *path;
};
-static struct wsp_res *wsp_tdata_new_res(struct wsp_tdata *d, void *ptr,
- enum wsp_res_t type)
-{
- struct wsp_res *res;
-
- res = kmalloc(sizeof(*res), GFP_ATOMIC);
- if (res) {
- INIT_LIST_HEAD(&res->list);
- res->ptr = ptr;
- res->id = wsp_tdata_get_id();
- res->type = type;
- res->stat = WRS_NEW;
+static LIST_HEAD(__resources_list);
+static DEFINE_MUTEX(__resources_mutex);
- /* add to list */
- spin_lock(&d->lock);
- list_add(&res->list, &d->res_list);
- spin_unlock(&d->lock);
- }
-
- return res;
-}
-
-static void wsp_tdata_del_res(struct wsp_res *res)
+static struct wsp_resource_data *wsp_resource_data_alloc(void)
{
- list_del(&res->list);
- kfree(res);
-}
-
-static struct wsp_tdata *wsp_tdata_create(void)
-{
- struct wsp_tdata *d;
-
- d = kmalloc(sizeof(*d), GFP_ATOMIC);
- if (d) {
- INIT_LIST_HEAD(&d->res_list);
- spin_lock_init(&d->lock);
- d->stat = TDS_NEW;
- }
-
- return d;
-}
+ struct wsp_resource_data *p;
-static void wsp_tdata_destroy(struct wsp_tdata *d)
-{
- struct wsp_res *res, *n;
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return NULL;
- spin_lock(&d->lock);
- list_for_each_entry_safe(res, n, &d->res_list, list)
- wsp_tdata_del_res(res);
- spin_unlock(&d->lock);
+ INIT_LIST_HEAD(&p->list);
- kfree(d);
+ return p;
}
-static struct wsp_res *wsp_tdata_last_res(struct wsp_tdata *d)
+static void wsp_resource_data_free(struct wsp_resource_data *p)
{
- struct wsp_res *res;
+ if (!p)
+ return;
- spin_lock(&d->lock);
- res = list_first_entry_or_null(&d->res_list, struct wsp_res, list);
- spin_unlock(&d->lock);
-
- return res;
+ kfree(p->path);
+ kfree(p);
}
-struct wsp_res *wsp_tdata_find_res(struct wsp_tdata *data, void *ptr,
- enum wsp_res_t type)
+static struct wsp_resource_data *wsp_resource_data_find(unsigned long addr)
{
- struct wsp_res *res;
-
- list_for_each_entry(res, &data->res_list, list) {
- if (res->type != type)
- continue;
+ struct wsp_resource_data *p;
- if (res->ptr == ptr) {
- if (res->stat == WRS_ERR) {
- pr_err("ERR: something went wrong\n");
- return NULL;
- }
-
- return res;
- }
- }
+ list_for_each_entry(p, &__resources_list, list)
+ if (p->addr == addr)
+ return p;
return NULL;
}
-
-
-
-
-/* ============================================================================
- * = wsp_current_[get/set]_stat() =
- * ============================================================================
- */
-enum tdata_stat wsp_current_get_stat(void)
+int wsp_resource_data_id(unsigned long addr)
{
- struct wsp_tdata *d;
+ int ret = -1;
+ struct wsp_resource_data *p;
- d = get_tdata();
- if (d)
- return d->stat;
- else
- pr_err("ERR: no current tdata\n");
+ mutex_lock(&__resources_mutex);
+ p = wsp_resource_data_find(addr);
+ if (p)
+ ret = p->id;
+ mutex_unlock(&__resources_mutex);
- return TDS_ERR;
+ return ret;
}
-void wsp_current_set_stat(enum tdata_stat stat)
+int wsp_resource_data_add(unsigned long addr, char *path)
{
- struct wsp_tdata *d;
-
- d = get_tdata();
- if (d)
- d->stat = stat;
- else
- pr_err("ERR: no current tdata\n");
-}
-
-
-
+ int ret = -1;
+ struct wsp_resource_data *p;
-
-/* ============================================================================
- * = wsp_res =
- * ============================================================================
- */
-struct wsp_res *wsp_res_new(void *ptr, enum wsp_res_t type)
-{
- struct wsp_tdata *data;
-
- data = get_tdata();
- if (data == NULL) {
- pr_err("ERR: no current tdata\n");
- return NULL;
+ mutex_lock(&__resources_mutex);
+ p = wsp_resource_data_find(addr);
+ if (p) {
+ ret = p->id;
+ goto out;
}
-
-
- return wsp_tdata_new_res(data, ptr, type);
-}
-
-void wsp_res_del(struct wsp_res *res)
-{
- wsp_tdata_del_res(res);
-}
-
-struct wsp_res *wsp_res_find(void *ptr, enum wsp_res_t type)
-{
- struct wsp_tdata *data;
-
- data = get_tdata();
- if (data == NULL) {
- pr_err("ERR: no current tdata\n");
- return NULL;
+ p = wsp_resource_data_alloc();
+ if (p) {
+ p->id = __wsp_resource_id();
+ p->addr = addr;
+ p->path = path;
+ list_add_tail(&p->list, &__resources_list);
+ ret = p->id;
}
- return wsp_tdata_find_res(data, ptr, type);
-}
-
-struct wsp_res *wsp_res_last(void)
-{
- struct wsp_tdata *d;
-
- d = get_tdata();
- if (d == NULL) {
- pr_err("ERR: no current tdata\n");
- return NULL;
- }
+out:
+ mutex_unlock(&__resources_mutex);
- return wsp_tdata_last_res(d);
+ return ret;
}
-int wsp_res_stat_set_next(struct wsp_res *res, enum wsp_res_stat stat)
+void wsp_resource_data_del(unsigned long addr)
{
- switch (res->stat) {
- case WRS_NEW:
- if (stat == WRS_WILL_REQ) {
- res->stat = stat;
- return 0;
- }
- break;
-
- case WRS_WILL_REQ:
- if (stat == WRS_SOUP_REQ) {
- res->stat = stat;
- return 0;
- }
- break;
-
- case WRS_SOUP_REQ:
- case WRS_ADD_DATA:
- if (stat == WRS_ADD_DATA || stat == WRS_FINISH) {
- res->stat = stat;
- return 0;
- }
- break;
+ struct wsp_resource_data *p;
- default:
- break;
+ mutex_lock(&__resources_mutex);
+ p = wsp_resource_data_find(addr);
+ if (p) {
+ list_del(&p->list);
+ wsp_resource_data_free(p);
}
- pr_err("ERR: set_next_stat from %d to %d [id=%d]\n",
- res->stat, stat, res->id);
-
- res->stat = WRS_ERR;
-
- return -1;
+ mutex_unlock(&__resources_mutex);
}
-
-
-
-
/* ============================================================================
* = init/exit() =
* ============================================================================
*/
int wsp_res_init(void)
{
- g_tdata = wsp_tdata_create();
- if (g_tdata == NULL)
- return -ENOMEM;
-
- atomic_set(&wsp_res_count, 0);
-
return 0;
}
void wsp_res_exit(void)
{
- wsp_tdata_destroy(g_tdata);
- g_tdata = NULL;
+ struct wsp_resource_data *p, *tmp;
+
+ mutex_lock(&__resources_mutex);
+ list_for_each_entry_safe(p, tmp, &__resources_list, list) {
+ list_del(&p->list);
+ wsp_resource_data_free(p);
+ }
+ mutex_unlock(&__resources_mutex);
}
#define _WSP_TDATA_H
/*
+ * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * @section LICENSE
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * @section COPYRIGHT
*
* Copyright (C) Samsung Electronics, 2015
*
- * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ * @section DESCRIPTION
*
+ * Web startup profiling
*/
-
#include <linux/types.h>
-
-enum tdata_stat {
- TDS_ERR,
- TDS_NEW,
- TDS_FINISH_MAIN_LOAD,
- TDS_DRAW
-};
-
-enum wsp_res_t {
- WR_NONE,
- WR_MAIN,
- WR_ANY
-};
-
-enum wsp_res_stat {
- WRS_NEW,
- WRS_WILL_REQ,
- WRS_SOUP_REQ,
- WRS_ADD_DATA,
- WRS_FINISH,
- WRS_ERR
-};
-
-struct wsp_res {
- struct list_head list;
- void *ptr;
- int id;
- enum wsp_res_t type;
- enum wsp_res_stat stat;
-};
-
-
-enum tdata_stat wsp_current_get_stat(void);
-void wsp_current_set_stat(enum tdata_stat stat);
-
-struct wsp_res *wsp_res_new(void *ptr, enum wsp_res_t type);
-void wsp_res_del(struct wsp_res *res);
-
-struct wsp_res *wsp_res_last(void);
-struct wsp_res *wsp_res_find(void *ptr, enum wsp_res_t type);
-
-int wsp_res_stat_set_next(struct wsp_res *res, enum wsp_res_stat stat);
+int wsp_resource_data_add(unsigned long addr, char *path);
+void wsp_resource_data_del(unsigned long addr);
+int wsp_resource_data_id(unsigned long addr);
int wsp_res_init(void);
void wsp_res_exit(void);
-
#endif /* _WSP_TDATA_H */