void * swap (void) { struct frame_entry *victim_frame = find_victim(); struct spage_entry *victim_spage_entry = victim_frame->spe; uint32_t sectornum = swap_out(victim_frame->frame); pagedir_clear_page(victim_frame->t->pagedir,victim_spage_entry->uaddr); victim_spage_entry->indisk = true; victim_spage_entry->sec_no = sectornum; palloc_free_page(victim_frame->frame); falloc_free_frame(victim_frame->frame); void *kpage = palloc_get_page(PAL_USER|PAL_ZERO); ASSERT(kpage != NULL); return kpage; }
int main(int argc, char** argv) { static struct option longopts[] = { { "daemonize", no_argument, NULL, 'd' }, { "cgroup", required_argument, NULL, 'g' }, { "pidfile", required_argument, NULL, 'p'}, { "restart_on_crash", no_argument, NULL, 'r'}, { "verbose", no_argument, NULL, 'v'}, { NULL, 0, NULL, 0} }; int cl; char* event_command; char* event_control_path; char* oom_control_path; char* pidfile = NULL; uint64_t efdcounter; struct sigaction sa; int flag; assert(argc > 1); exit_flag = 0; restart_flag = 0; char daemon_flag = 0; char restart_on_crash_flg = 0; struct cgroup_context cgc; char verbose_log = 0; cgc.cgroup_name = NULL; int ch; while((ch = getopt_long(argc, argv, "rvdg:p:", longopts, NULL)) != -1) { switch(ch) { case 'd': daemon_flag = 1; break; case 'g': asprintf(&cgc.cgroup_name, "%s", optarg); break; case 'p': asprintf(&pidfile, "%s", optarg); break; case 'r': restart_on_crash_flg = 1; break; case 'v': verbose_log = 1; break; default: break; } } if(cgc.cgroup_name == NULL) { slog(LOG_ALERT, "FATAL: No cgroup specified, exiting"); abort(); } if(daemon_flag) { if(daemon(0,0) == -1) { slog(LOG_ALERT, "FATAL: failed to daemonize!"); abort(); } if(pidfile) { pid_t pid = getpid(); FILE* f = fopen(pidfile, "w"); if(!f) { slog(LOG_ALERT, "FATAL: Failed to write to pidfile"); abort(); } fprintf(f, "%d", pid); fclose(f); free(pidfile); pidfile = NULL; } } cgc.efd = eventfd(0,0); assert(cgc.efd != -1); cgroup_init(); cgroup_get_subsys_mount_point("memory", &((cgc.cgroup_path))); cgroup_get_subsys_mount_point("freezer", &((cgc.freezer_path))); cgc.purgatory = cgroup_new_cgroup("purgatory"); cgroup_add_controller(cgc.purgatory, "freezer"); cgroup_create_cgroup(cgc.purgatory,1); char* purgatory_freeze_path; FILE* freezer_fd; asprintf(&purgatory_freeze_path, "/%s/purgatory/freezer.state", cgc.freezer_path); freezer_fd = fopen(purgatory_freeze_path,"w"); fprintf(freezer_fd, "FROZEN"); fclose(freezer_fd); free(purgatory_freeze_path); asprintf(&event_control_path, "/%s/%s/cgroup.event_control", cgc.cgroup_path, cgc.cgroup_name); cgc.ecfd = open(event_control_path, O_WRONLY); if(cgc.ecfd < 0) { slog(LOG_ALERT, "FATAL: failed to open cgroup event control: %s\n", event_control_path); perror("cgroup.event_control"); } asprintf(&oom_control_path, "/%s/%s/memory.oom_control", cgc.cgroup_path, cgc.cgroup_name); cgc.oomfd = open(oom_control_path, O_RDONLY); if(!(cgc.oomfd >=0)) { slog(LOG_ALERT, "FATAL: Failed to open oom_control"); abort(); } cl = asprintf(&event_command, "%d %d", cgc.efd, cgc.oomfd); write(cgc.ecfd, event_command, cl); free(event_control_path); free(event_command); free(oom_control_path); setjmp(exit_stack); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NOMASK; sa.sa_handler = exit_handler; sigaction(SIGINT, &sa, NULL); if(restart_on_crash_flg) //optionally make an effort to handle crashes { sa.sa_handler = crash_handler; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGBUS, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); sigaction(SIGABRT, &sa, NULL); } if(restart_flag < 2) //try to handle recursive faults { stop_oomkiller(&cgc); while(!exit_flag) { read(cgc.efd, &efdcounter, sizeof(uint64_t)); flag = 0; //stop killing if the task list is empty (shouldn't happen) if(verbose_log) log_process_table(); //dump process list to syslog while(is_oom(&cgc) && flag >= 0) { flag = find_victim(&cgc); usleep(100); //give processes a chance to die } } cgroup_delete_cgroup(cgc.purgatory, 0); start_oomkiller(&cgc); close(cgc.oomfd); close(cgc.ecfd); } if(restart_flag) { char* args[argc+1]; int i; for(i=0;i<argc;i++) { asprintf(&(args[i]), "%s", argv[i]); } args[argc] = NULL; execv(argv[0], args); } }