2 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include <sys/types.h>
28 #include "ss_device_plugin.h"
32 #include "include/ss_data.h"
34 #define DELETE_SM "sh -c "PREFIX"/bin/delete.sm"
36 #define MEMNOTIFY_NORMAL 0x0000
37 #define MEMNOTIFY_LOW 0xfaac
38 #define MEMNOTIFY_CRITICAL 0xdead
39 #define MEMNOTIFY_REBOOT 0xb00f
41 #define _SYS_RES_CLEANUP "RES_CLEANUP"
43 #define MEM_THRESHOLD_LV1 60
44 #define MEM_THRESHOLD_LV2 40
47 struct lowmem_process_entry {
48 unsigned cur_mem_state;
49 unsigned new_mem_state;
50 int (*action) (void *);
53 static int lowmem_fd = -1;
54 static int cur_mem_state = MEMNOTIFY_NORMAL;
56 Ecore_Timer *oom_timer;
57 #define OOM_TIMER_INTERVAL 5
59 static int memory_low_act(void *ad);
60 static int memory_oom_act(void *ad);
61 static int memory_normal_act(void *ad);
63 static struct lowmem_process_entry lpe[] = {
64 {MEMNOTIFY_NORMAL, MEMNOTIFY_LOW, memory_low_act},
65 {MEMNOTIFY_NORMAL, MEMNOTIFY_CRITICAL, memory_oom_act},
66 {MEMNOTIFY_LOW, MEMNOTIFY_CRITICAL, memory_oom_act},
67 {MEMNOTIFY_CRITICAL, MEMNOTIFY_CRITICAL, memory_oom_act},
68 {MEMNOTIFY_LOW, MEMNOTIFY_NORMAL, memory_normal_act},
69 {MEMNOTIFY_CRITICAL, MEMNOTIFY_NORMAL, memory_normal_act},
73 unsigned int oom_delete_sm_time = 0;
75 static int remove_shm()
78 struct shmid_ds shmseg;
79 struct shm_info shm_info;
81 maxid = shmctl(0, SHM_INFO, (struct shmid_ds *)(void *)&shm_info);
83 PRT_TRACE_ERR("shared mem error\n");
87 for (id = 0; id <= maxid; id++) {
88 shmid = shmctl(id, SHM_STAT, &shmseg);
91 if (shmseg.shm_nattch == 0) {
92 PRT_TRACE("shared memory killer ==> %d killed\n",
94 shmctl(shmid, IPC_RMID, NULL);
100 static char *convert_to_str(unsigned int mem_state)
104 case MEMNOTIFY_NORMAL:
110 case MEMNOTIFY_CRITICAL:
111 tmp = "mem critical";
113 case MEMNOTIFY_REBOOT:
122 static void print_lowmem_state(unsigned int mem_state)
124 PRT_TRACE("[LOW MEM STATE] %s ==> %s", convert_to_str(cur_mem_state),
125 convert_to_str(mem_state));
128 static int get_lowmemnotify_info(FILE *output_fp)
133 if (output_fp == NULL)
136 fp = fopen("/sys/class/memnotify/meminfo", "r");
139 PRT_TRACE("make LOWMEM_LOG");
141 "====================================================================\n");
142 fprintf(output_fp, "MEMORY INFO by lowmemnotify\n");
144 while (fgets(line, BUF_MAX, fp) != NULL) {
145 PRT_TRACE("%s",line);
146 fputs(line, output_fp);
153 static void make_LMM_log(char *file, pid_t pid, char *victim_name)
157 char new_log[NAME_MAX];
158 static pid_t old_pid = 0;
160 FILE *output_file = NULL;
167 cur_tm = (struct tm *)malloc(sizeof(struct tm));
168 if (cur_tm == NULL) {
169 PRT_TRACE_ERR("Fail to memory allocation");
173 if (localtime_r(&now, cur_tm) == NULL) {
174 PRT_TRACE_ERR("Fail to get localtime");
179 PRT_TRACE("%s_%s_%d_%.4d%.2d%.2d_%.2d%.2d%.2d.log", file, victim_name,
180 pid, (1900 + cur_tm->tm_year), 1 + cur_tm->tm_mon,
181 cur_tm->tm_mday, cur_tm->tm_hour, cur_tm->tm_min,
183 snprintf(new_log, sizeof(new_log),
184 "%s_%s_%d_%.4d%.2d%.2d_%.2d%.2d%.2d.log", file, victim_name,
185 pid, (1900 + cur_tm->tm_year), 1 + cur_tm->tm_mon,
186 cur_tm->tm_mday, cur_tm->tm_hour, cur_tm->tm_min,
189 output_file = fopen(new_log, "w+");
191 PRT_TRACE_ERR("cannot open output file(%s)",new_log);
195 get_lowmemnotify_info(output_file);
202 static int memory_low_act(void *data)
204 char lowmem_noti_name[NAME_MAX];
206 PRT_TRACE("[LOW MEM STATE] memory low state");
207 make_LMM_log("/var/log/memps", 1, "LOWMEM_WARNING");
210 heynoti_get_snoti_name(_SYS_RES_CLEANUP, lowmem_noti_name, NAME_MAX);
211 ss_noti_send(lowmem_noti_name);
212 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
213 VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING);
218 static int memory_oom_act(void *data)
220 unsigned int cur_time;
221 char lowmem_noti_name[NAME_MAX];
223 PRT_TRACE("[LOW MEM STATE] memory oom state");
224 cur_time = time(NULL);
225 PRT_TRACE("cur=%d, old=%d, cur-old=%d", cur_time, oom_delete_sm_time,
226 cur_time - oom_delete_sm_time);
227 if (cur_time - oom_delete_sm_time > 15) {
229 oom_delete_sm_time = cur_time;
230 /* Also clean up unreturned memory of applications */
231 heynoti_get_snoti_name(_SYS_RES_CLEANUP, lowmem_noti_name,
233 ss_noti_send(lowmem_noti_name);
235 ss_action_entry_call_internal(PREDEF_LOWMEM, 1, OOM_MEM_ACT);
237 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
238 VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING);
244 static int memory_normal_act(void *data)
246 PRT_TRACE("[LOW MEM STATE] memory normal state");
247 vconf_set_int(VCONFKEY_SYSMAN_LOW_MEMORY,
248 VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL);
252 static int lowmem_process(unsigned int mem_state, void *ad)
255 for (i = 0; i < sizeof(lpe) / sizeof(struct lowmem_process_entry); i++) {
256 if ((cur_mem_state == lpe[i].cur_mem_state)
257 && (mem_state == lpe[i].new_mem_state)) {
259 if(oom_timer != NULL) {
260 ecore_timer_del(oom_timer);
264 if(mem_state == MEMNOTIFY_CRITICAL)
265 oom_timer = ecore_timer_add(OOM_TIMER_INTERVAL,lpe[i].action, ad);
272 static unsigned int lowmem_read(int fd)
274 unsigned int mem_state;
275 read(fd, &mem_state, sizeof(mem_state));
279 static int lowmem_cb(void *data, Ecore_Fd_Handler * fd_handler)
282 struct ss_main_data *ad = (struct ss_main_data *)data;
283 unsigned int mem_state;
285 if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) {
287 ("ecore_main_fd_handler_active_get error , return\n");
291 fd = ecore_main_fd_handler_fd_get(fd_handler);
293 PRT_TRACE_ERR("ecore_main_fd_handler_fd_get error , return");
296 mem_state = lowmem_read(fd);
297 print_lowmem_state(mem_state);
298 lowmem_process(mem_state, ad);
299 cur_mem_state = mem_state;
304 static int set_threshold()
306 if (0 > plugin_intf->OEM_sys_set_memnotify_threshold_lv1(MEM_THRESHOLD_LV1)) {
307 PRT_TRACE_ERR("Set memnorify threshold lv1 failed");
311 if (0 > plugin_intf->OEM_sys_set_memnotify_threshold_lv2(MEM_THRESHOLD_LV2)) {
312 PRT_TRACE_ERR("Set memnorify threshold lv2 failed");
319 int ss_lowmem_init(struct ss_main_data *ad)
321 char lowmem_dev_node[PATH_MAX];
323 if (0 > plugin_intf->OEM_sys_get_memnotify_node(lowmem_dev_node)) {
324 PRT_TRACE_ERR("Low memory handler fd init failed");
328 lowmem_fd = open(lowmem_dev_node, O_RDONLY);
330 PRT_TRACE_ERR("ss_lowmem_init fd open failed");
335 ecore_main_fd_handler_add(lowmem_fd, ECORE_FD_READ, lowmem_cb, ad, NULL,
337 if (set_threshold() < 0) {
338 PRT_TRACE_ERR("Setting lowmem threshold is failed");