#define CPU_CHECKER_TIMEOUT 1000
#define PI 3.14159265
+enum candidate_process_state_e {
+ CANDIDATE_PROCESS_STATE_RUNNING,
+ CANDIDATE_PROCESS_STATE_PAUSED,
+};
+
typedef struct {
int type;
bool prepared;
bool on_boot;
bool app_exists;
bool touched;
+ int activation_method;
+ int deactivation_method;
+ unsigned int ttl;
+ guint live_timer;
+ int state;
} candidate_process_context_t;
typedef struct {
static app_labels_monitor *label_monitor;
static GList *launcher_info_list;
static GHashTable *__pid_table;
+static int __memory_status;
static candidate_process_context_t *__add_slot(int type, int loader_id,
int caller_pid, const char *loader_path, const char *extra,
- int detection_method, int timeout_val,
+ int detection_method, int activation_method,
+ int deactivation_method, unsigned int ttl, int timeout_val,
int threshold_max, int threshold_min, bool on_boot,
bool app_exists);
static int __remove_slot(int type, int loader_id);
static int __add_default_slots(void);
static gboolean __handle_idle_checker(gpointer data);
static int __add_idle_checker(int detection_method, GList *cur);
+static void __dispose_candidate_process(candidate_process_context_t *cpc);
+static bool __is_low_memory(void);
+static void __update_slot_state(candidate_process_context_t *cpc, int method);
+static void __set_idle_checker_timer(candidate_process_context_t *cpc);
static int __make_loader_id(void)
{
return -1;
}
+static gboolean __handle_deactivate_event(gpointer user_data)
+{
+ candidate_process_context_t *cpc;
+
+ cpc = (candidate_process_context_t *)user_data;
+ __update_slot_state(cpc, METHOD_TTL);
+ _D("Deactivate event: type(%d)", cpc->type);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void __set_live_timer(candidate_process_context_t *cpc)
+{
+ if (!cpc)
+ return;
+
+ if (cpc->deactivation_method & METHOD_TTL) {
+ if (cpc->live_timer == 0) {
+ cpc->live_timer = g_timeout_add_seconds(cpc->ttl,
+ __handle_deactivate_event, cpc);
+ }
+ }
+}
+
static int __prepare_candidate_process(int type, int loader_id)
{
int pid;
}
cpt->pid = pid;
+ __set_live_timer(cpt);
return 0;
}
-static gboolean __handle_timeout_event(gpointer user_data)
+static void __set_idle_checker_timer(candidate_process_context_t *cpc)
{
- candidate_process_context_t *cpc;
unsigned long long total = 0;
unsigned long long idle = 0;
- cpc = (candidate_process_context_t *)user_data;
- cpc->timer = 0;
-
if (cpc->idle_checker > 0)
- return G_SOURCE_REMOVE;
+ return;
_get_cpu_idle(&total, &idle);
cpc->cpu_idle_time = idle;
cpc->cpu_total_time = total;
- _D("Add idle checker");
cpc->idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
__handle_idle_checker,
g_list_find(candidate_slot_list, cpc));
+ _D("Add idle checker: type(%d)", cpc->type);
+}
+static gboolean __handle_timeout_event(gpointer user_data)
+{
+ candidate_process_context_t *cpc;
+
+ cpc = (candidate_process_context_t *)user_data;
+ cpc->timer = 0;
+
+ if (cpc->idle_checker > 0)
+ return G_SOURCE_REMOVE;
+
+ __set_idle_checker_timer(cpc);
return G_SOURCE_REMOVE;
}
static void __set_timer(candidate_process_context_t *cpc)
{
- if (cpc == NULL)
+ if (cpc == NULL || cpc->timer > 0)
return;
- if (cpc->detection_method & METHOD_TIMEOUT) {
+ if ((cpc->detection_method & METHOD_TIMEOUT) &&
+ cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) {
cpc->timer = g_timeout_add(cpc->timeout_val,
__handle_timeout_event, cpc);
}
cpc->source = 0;
cpc->timer = 0;
cpc->idle_checker = 0;
+ cpc->live_timer = 0;
+}
+
+static void __dispose_candidate_process(candidate_process_context_t *cpc)
+{
+ if (!cpc)
+ return;
+
+ _D("Dispose candidate process %d", cpc->type);
+ if (cpc->pid > 0) {
+ _D("kill process %d", cpc->pid);
+ __kill_process(cpc->pid);
+ }
+ if (cpc->live_timer > 0)
+ g_source_remove(cpc->live_timer);
+ if (cpc->source > 0)
+ g_source_remove(cpc->source);
+ if (cpc->timer > 0)
+ g_source_remove(cpc->timer);
+ if (cpc->idle_checker > 0)
+ g_source_remove(cpc->idle_checker);
+ if (cpc->send_fd > 0)
+ close(cpc->send_fd);
+ __reset_slot(cpc);
}
static int __send_launchpad_loader(candidate_process_context_t *cpc,
cpc->pid, app_path);
pid = cpc->pid;
-
- if (cpc->send_fd > 0)
- close(cpc->send_fd);
- if (cpc->source > 0)
- g_source_remove(cpc->source);
- if (cpc->timer > 0)
- g_source_remove(cpc->timer);
- if (cpc->idle_checker > 0)
- g_source_remove(cpc->idle_checker);
-
- __reset_slot(cpc);
+ cpc->pid = CANDIDATE_NONE;
+ __dispose_candidate_process(cpc);
__set_timer(cpc);
return pid;
}
SECURE_LOGE("Type %d candidate process was " \
"(POLLHUP|POLLNVAL), pid: %d",
cpc->type, cpc->pid);
- if (cpc->send_fd > 0)
- close(cpc->send_fd);
- if (cpc->timer > 0)
- g_source_remove(cpc->timer);
- if (cpc->idle_checker > 0)
- g_source_remove(cpc->idle_checker);
-
- __reset_slot(cpc);
-
+ cpc->pid = CANDIDATE_NONE;
+ __dispose_candidate_process(cpc);
__prepare_candidate_process(cpc->type, cpc->loader_id);
-
return G_SOURCE_REMOVE;
}
cpc = __find_slot_from_pid(siginfo.ssi_pid);
if (cpc != NULL) {
- __reset_slot(cpc);
+ cpc->pid = CANDIDATE_NONE;
+ __dispose_candidate_process(cpc);
__prepare_candidate_process(cpc->type, cpc->loader_id);
}
while (iter) {
cpc = (candidate_process_context_t *)iter->data;
if (cpc->pid > 0) {
- if (cpc->source > 0)
- g_source_remove(cpc->source);
- if (cpc->timer > 0)
- g_source_remove(cpc->timer);
- if (cpc->idle_checker > 0)
- g_source_remove(cpc->idle_checker);
- if (cpc->send_fd > 0)
- close(cpc->send_fd);
- _D("Dispose candidate process %d", cpc->pid);
- __kill_process(cpc->pid);
- __reset_slot(cpc);
+ __dispose_candidate_process(cpc);
__prepare_candidate_process(cpc->type, cpc->loader_id);
}
{
candidate_process_context_t *cpc;
GList *iter = cur;
- unsigned long long total = 0;
- unsigned long long idle = 0;
while (iter) {
cpc = (candidate_process_context_t *)iter->data;
+ if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) {
+ iter = g_list_next(iter);
+ continue;
+ }
if (strcmp("null", cpc->loader_path) == 0) {
iter = g_list_next(iter);
}
if (cpc->idle_checker == 0) {
- _get_cpu_idle(&total, &idle);
- cpc->cpu_idle_time = idle;
- cpc->cpu_total_time = total;
cpc->cur_event = detection_method;
- cpc->idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
- __handle_idle_checker, iter);
- _D("Add Idler checker");
+ __set_idle_checker_timer(cpc);
return 0;
}
}
lid = __make_loader_id();
cpc = __add_slot(LAUNCHPAD_TYPE_DYNAMIC, lid, atoi(caller_pid),
add_slot_str, extra,
- METHOD_TIMEOUT | METHOD_VISIBILITY, 2000,
+ METHOD_TIMEOUT | METHOD_VISIBILITY,
+ METHOD_REQUEST | METHOD_AVAILABLE_MEMORY,
+ METHOD_TTL | METHOD_OUT_OF_MEMORY,
+ 600,
+ 2000,
DEFAULT_CPU_THRESHOLD_MAX,
DEFAULT_CPU_THRESHOLD_MIN,
false,
static void __update_slot(int type, bool app_exists)
{
candidate_process_context_t *cpc;
- unsigned long long total = 0;
- unsigned long long idle = 0;
cpc = __find_slot(type, PAD_LOADER_ID_STATIC);
if (!cpc)
cpc->app_exists = app_exists;
if (!cpc->app_exists) {
- if (cpc->pid > 0) {
- if (cpc->source > 0)
- g_source_remove(cpc->source);
- if (cpc->timer > 0)
- g_source_remove(cpc->timer);
- if (cpc->idle_checker > 0)
- g_source_remove(cpc->idle_checker);
- if (cpc->send_fd > 0)
- close(cpc->send_fd);
- _D("Dispose candidate process %d", cpc->pid);
- __kill_process(cpc->pid);
- __reset_slot(cpc);
- }
+ if (cpc->pid > 0)
+ __dispose_candidate_process(cpc);
} else {
+ if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING)
+ return;
+
if (!cpc->touched && !cpc->on_boot)
return;
}
if (cpc->pid == CANDIDATE_NONE &&
- cpc->idle_checker == 0) {
- _get_cpu_idle(&total, &idle);
- cpc->cpu_idle_time = idle;
- cpc->cpu_total_time = total;
- _D("Add idle checker");
- cpc->idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT,
- __handle_idle_checker,
- g_list_find(candidate_slot_list, cpc));
- }
+ cpc->idle_checker == 0)
+ __set_idle_checker_timer(cpc);
}
}
return 0;
}
+static void __update_slot_state(candidate_process_context_t *cpc, int method)
+{
+ if (method == METHOD_OUT_OF_MEMORY) {
+ if ((cpc->deactivation_method & method) && __is_low_memory()) {
+ cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
+ __dispose_candidate_process(cpc);
+ } else {
+ cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
+ if (!cpc->touched && !cpc->on_boot)
+ return;
+ if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE)
+ return;
+ if (cpc->detection_method & METHOD_TIMEOUT)
+ __set_timer(cpc);
+ }
+ } else if (cpc->activation_method & method) {
+ __update_slot_state(cpc, METHOD_OUT_OF_MEMORY);
+ } else if (cpc->deactivation_method & method) {
+ cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
+ __dispose_candidate_process(cpc);
+ } else {
+ cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
+ if (!cpc->touched && !cpc->on_boot)
+ return;
+ if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE)
+ return;
+ if (cpc->detection_method & METHOD_TIMEOUT)
+ __set_timer(cpc);
+ }
+}
+
static gboolean __handle_launch_event(gpointer data)
{
loader_context_t *lc = (loader_context_t *) data;
org_cpc->idle_checker = 0;
}
+ __update_slot_state(org_cpc, METHOD_REQUEST);
__set_timer(org_cpc);
}
} else {
static candidate_process_context_t *__add_slot(int type, int loader_id,
int caller_pid, const char *loader_path,
const char *loader_extra, int detection_method,
- int timeout_val, int threshold_max, int threshold_min,
+ int activation_method, int deactivation_method,
+ unsigned int ttl, int timeout_val,
+ int threshold_max, int threshold_min,
bool on_boot, bool app_exists)
{
candidate_process_context_t *cpc;
cpc->app_exists = app_exists;
cpc->touched = false;
cpc->cur_event = 0;
+ cpc->activation_method = activation_method;
+ cpc->deactivation_method = deactivation_method;
+ cpc->ttl = ttl;
+ cpc->live_timer = 0;
+
+ if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) &&
+ __is_low_memory())
+ cpc->state = CANDIDATE_PROCESS_STATE_PAUSED;
+ else
+ cpc->state = CANDIDATE_PROCESS_STATE_RUNNING;
fd = __listen_candidate_process(cpc->type, cpc->loader_id);
if (fd == -1) {
while (iter) {
cpc = (candidate_process_context_t *)iter->data;
if (type == cpc->type && loader_id == cpc->loader_id) {
- if (cpc->pid > 0)
- __kill_process(cpc->pid);
- if (cpc->timer > 0)
- g_source_remove(cpc->timer);
- if (cpc->source > 0)
- g_source_remove(cpc->source);
- if (cpc->idle_checker > 0)
- g_source_remove(cpc->idle_checker);
-
+ __dispose_candidate_process(cpc);
candidate_slot_list = g_list_delete_link(
candidate_slot_list, iter);
free(cpc->loader_path);
if (!strcmp(info->exe, "null")) {
cpc = __add_slot(LAUNCHPAD_TYPE_USER + user_slot_offset,
PAD_LOADER_ID_DIRECT,
- 0, info->exe, NULL, 0, 0,
+ 0, info->exe, NULL,
+ 0, 0, 0, 0, 0,
info->cpu_threshold_max,
info->cpu_threshold_min,
false,
cpc = __add_slot(LAUNCHPAD_TYPE_USER + user_slot_offset,
PAD_LOADER_ID_STATIC,
0, info->exe, (char *)extra,
- info->detection_method, info->timeout_val,
+ info->detection_method,
+ info->activation_method,
+ info->deactivation_method,
+ info->ttl,
+ info->timeout_val,
info->cpu_threshold_max,
info->cpu_threshold_min,
info->on_boot,
return 0;
}
-static void __vconf_cb(keynode_t *key, void *data)
+static bool __is_low_memory(void)
{
- const char *name;
+ if (__memory_status >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
+ return true;
+ return false;
+}
- name = vconf_keynode_get_name(key);
- if (name && strcmp(name, VCONFKEY_SETAPPL_APP_HW_ACCELERATION) == 0) {
- __sys_hwacc = vconf_keynode_get_int(key);
- _D("sys hwacc: %d", __sys_hwacc);
- }
+static void __hw_acceleration_changed_cb(keynode_t *key, void *data)
+{
+ __sys_hwacc = vconf_keynode_get_int(key);
+ _D("sys hwacc: %d", __sys_hwacc);
}
static void __update_lang(keynode_t *node, void *user_data)
setenv("LANG", lang, 1);
}
+static void __memory_status_changed_cb(keynode_t *node, void *data)
+{
+ candidate_process_context_t *cpc;
+ GList *iter = candidate_slot_list;
+
+ __memory_status = vconf_keynode_get_int(node);
+ if (__memory_status >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) {
+ _W("Low memory");
+ while (iter) {
+ cpc = (candidate_process_context_t *)iter->data;
+ __update_slot_state(cpc, METHOD_OUT_OF_MEMORY);
+ iter = g_list_next(iter);
+ }
+ } else {
+ _W("Normal");
+ while (iter) {
+ cpc = (candidate_process_context_t *)iter->data;
+ __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY);
+ iter = g_list_next(iter);
+ }
+ }
+}
+
+static void __unregister_vconf_events(void)
+{
+ vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
+ __memory_status_changed_cb);
+ vconf_ignore_key_changed(VCONFKEY_LANGSET,
+ __update_lang);
+ vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
+ __hw_acceleration_changed_cb);
+}
+
+static int __register_vconf_events(void)
+{
+ int r;
+ char *lang;
+
+ r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
+ if (r != VCONF_OK)
+ _E("Failed to get vconf hw acceleration. err = %d", r);
+
+ r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
+ __hw_acceleration_changed_cb, NULL);
+ if (r != VCONF_OK) {
+ _E("Failed to register callback for hw acceleration. err = %d",
+ r);
+ }
+
+ lang = vconf_get_str(VCONFKEY_LANGSET);
+ if (lang) {
+ setenv("LANG", lang, 1);
+ free(lang);
+ }
+
+ r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
+ if (r != VCONF_OK)
+ _E("Failed to register callback for langset. err = %d", r);
+
+ r = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &__memory_status);
+ if (r != VCONF_OK)
+ _E("Failed to get vconf low memory. err = %d", r);
+
+ r = vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY,
+ __memory_status_changed_cb, NULL);
+ if (r != 0)
+ _E("Failed to register callback for low memory. err = %d", r);
+
+ return 0;
+}
+
static int __before_loop(int argc, char **argv)
{
int ret;
- char *lang;
ret = __init_sigchild_fd();
if (ret != 0) {
return -1;
}
- ret = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc);
- if (ret != VCONF_OK) {
- _E("Failed to get vconf int: %s",
- VCONFKEY_SETAPPL_APP_HW_ACCELERATION);
- }
-
- ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION,
- __vconf_cb, NULL);
- if (ret != 0) {
- _E("Failed to register callback for %s",
- VCONFKEY_SETAPPL_APP_HW_ACCELERATION);
- }
-
- lang = vconf_get_str(VCONFKEY_LANGSET);
- if (lang) {
- setenv("LANG", lang, 1);
- free(lang);
- }
-
- ret = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL);
- if (ret != 0)
- _E("Failed to register callback for %s", VCONFKEY_LANGSET);
-
ret = __init_label_monitor_fd();
if (ret != 0)
_W("Failed to initialize label monitor");
return -1;
}
+ __register_vconf_events();
+
return 0;
}
static void __after_loop(void)
{
+ __unregister_vconf_events();
if (__pid_table)
g_hash_table_destroy(__pid_table);
#include "loader_info.h"
#include "launchpad_common.h"
-#define TAG_LOADER "[LOADER]"
-#define TAG_NAME "NAME"
-#define TAG_EXE "EXE"
-#define TAG_APP_TYPE "APP_TYPE"
-#define TAG_DETECTION_METHOD "DETECTION_METHOD"
-#define TAG_TIMEOUT "TIMEOUT"
-#define TAG_EXTRA "EXTRA"
-#define TAG_EXTRA_ARRAY "EXTRA_ARRAY"
-#define TAG_EXTRA_ARRAY_VAL "EXTRA_ARRAY_VAL"
-#define TAG_ALTERNATIVE_LOADER "ALTERNATIVE_LOADER"
-#define TAG_HW_ACC "HW_ACC"
-#define TAG_CPU_THRESHOLD_MAX "CPU_THRESHOLD_MAX"
-#define TAG_CPU_THRESHOLD_MIN "CPU_THRESHOLD_MIN"
-#define TAG_ON_BOOT "ON_BOOT"
-#define VAL_ON "ON"
-#define VAL_OFF "OFF"
-#define VAL_METHOD_TIMEOUT "TIMEOUT"
-#define VAL_METHOD_DEMAND "DEMAND"
-#define VAL_METHOD_VISIBILITY "VISIBILITY"
-
+#define TAG_LOADER "[LOADER]"
+#define TAG_NAME "NAME"
+#define TAG_EXE "EXE"
+#define TAG_APP_TYPE "APP_TYPE"
+#define TAG_DETECTION_METHOD "DETECTION_METHOD"
+#define TAG_ACTIVATION_METHOD "ACTIVATION_METHOD"
+#define TAG_DEACTIVATION_METHOD "DEACTIVATION_METHOD"
+#define TAG_TTL "TTL"
+#define TAG_TIMEOUT "TIMEOUT"
+#define TAG_EXTRA "EXTRA"
+#define TAG_EXTRA_ARRAY "EXTRA_ARRAY"
+#define TAG_EXTRA_ARRAY_VAL "EXTRA_ARRAY_VAL"
+#define TAG_ALTERNATIVE_LOADER "ALTERNATIVE_LOADER"
+#define TAG_HW_ACC "HW_ACC"
+#define TAG_CPU_THRESHOLD_MAX "CPU_THRESHOLD_MAX"
+#define TAG_CPU_THRESHOLD_MIN "CPU_THRESHOLD_MIN"
+#define TAG_ON_BOOT "ON_BOOT"
+
+#define VAL_ON "ON"
+#define VAL_OFF "OFF"
+#define VAL_METHOD_TIMEOUT "TIMEOUT"
+#define VAL_METHOD_DEMAND "DEMAND"
+#define VAL_METHOD_VISIBILITY "VISIBILITY"
+#define VAL_METHOD_REQUEST "REQUEST"
+#define VAL_METHOD_AVAILABLE_MEMORY "AVAILABLE_MEMORY"
+#define VAL_METHOD_TTL "TTL"
+#define VAL_METHOD_OUT_OF_MEMORY "OUT_OF_MEMORY"
static loader_info_t *__create_loader_info()
{
info->cpu_threshold_min = DEFAULT_CPU_THRESHOLD_MIN;
info->on_boot = true;
info->app_exists = false;
+ info->activation_method = 0;
+ info->deactivation_method = 0;
+ info->ttl = 600; /* 10 minutes */
return info;
}
_D("detection_method:%d", info->detection_method);
}
+static void __parse_activation_method(loader_info_t *info, char *line)
+{
+ char *token;
+ char *savedptr;
+
+ token = strtok_r(line, " |\t\r\n", &savedptr);
+ info->activation_method = 0;
+ while (token) {
+ if (!strcmp(token, VAL_METHOD_REQUEST))
+ info->activation_method |= METHOD_REQUEST;
+ else if (!strcmp(token, VAL_METHOD_AVAILABLE_MEMORY))
+ info->activation_method |= METHOD_AVAILABLE_MEMORY;
+
+ token = strtok_r(NULL, " |\t\r\n", &savedptr);
+ }
+
+ _D("activation_method:%d", info->activation_method);
+}
+
+static void __parse_deactivation_method(loader_info_t *info, char *line)
+{
+ char *token;
+ char *savedptr;
+
+ token = strtok_r(line, " |\t\r\n", &savedptr);
+ info->deactivation_method = 0;
+ while (token) {
+ if (!strcmp(token, VAL_METHOD_TTL))
+ info->deactivation_method |= METHOD_TTL;
+ else if (!strcmp(token, VAL_METHOD_OUT_OF_MEMORY))
+ info->deactivation_method |= METHOD_OUT_OF_MEMORY;
+
+ token = strtok_r(NULL, " |\t\r\n", &savedptr);
+ }
+
+ _D("deactivation_method:%d", info->deactivation_method);
+}
+
static void __parse_app_types(loader_info_t *info, char *line)
{
char *token;
__parse_app_types(cur_info, &buf[strlen(tok1)]);
} else if (strcasecmp(TAG_DETECTION_METHOD, tok1) == 0) {
__parse_detection_method(cur_info, &buf[strlen(tok1)]);
+ } else if (strcasecmp(TAG_ACTIVATION_METHOD, tok1) == 0) {
+ __parse_activation_method(cur_info,
+ &buf[strlen(tok1)]);
+ } else if (strcasecmp(TAG_DEACTIVATION_METHOD, tok1) == 0) {
+ __parse_deactivation_method(cur_info,
+ &buf[strlen(tok1)]);
+ } else if (strcasecmp(TAG_TTL, tok1) == 0) {
+ cur_info->ttl = strtoul(tok2, NULL, 10);
} else if (strcasecmp(TAG_TIMEOUT, tok1) == 0) {
cur_info->timeout_val = atoi(tok2);
} else if (strcasecmp(TAG_EXTRA, tok1) == 0) {