/* * free_disk (disk) - free the allocated memory */ void free_disk (struct list *disk) { if (disk != NULL) { if (disk->next != NULL) free_disk(disk->next); free(disk); } }
void VM_free(VMPTR_TYPE i) { VMPTR p; VMHEAD HUGE *h, HUGE *t; FNAME(VM_free); TEST(fun, 0); p.i = i; if (!i || p.p.b >= VMBASESIZ || p.p.l >= VMLEGSIZ || !VMbase[p.p.b]) return; h = (VMHEAD HUGE *) &VMbase[p.p.b][p.p.l]; if (h->type == MT_NOTUSED) return; if (h->type & MT_IMEDIATE) { if (h->type & MT_FREEZE) { VMnfreez--; VMnifrez--; } vmfree_head(i); VMlive--; TEST(fun, 1); return; } VMtotal -= h->size; free_disk(h->size, h->diskadd, 0); /* this must be redone because free_disk calls dfree_new, rmalloc, compact so the address may change */ h = (VMHEAD HUGE *) &VMbase[p.p.b][p.p.l]; if (h->type & MT_FREEZE) VMnfreez--; if (h->type & MT_DISK) { vmfree_head(i); VMdisk--; TEST(fun, 2); return; } if (!(h->type & MT_FREEZE)) vm_unlink(h); rmfree((RMHEAD_PTR) h->mem, h->size); vmfree_head(i); VMlive--; TEST(fun, 3); }
static long disk_next(long s, char HUGE *buf) { /* variable prefix: b=best, c=current */ /* variable suffix: a=address, s=size, i=index */ register int ci, bi; long bs, cs, da = -1L; DFREE HUGE *ca, HUGE *ba; int rtf = 1; FNAME(disk_next); retry: if (DMnfree >= s) { bi = -1; bs = 0L; ca = DMflist; for ( ; ca && bs != s ; ca = ca->next) for (ci=0 ; ci != DHEADSIZE ; ++ci) if ((cs=ca->nfree[ci]) == s) { bi = ci; bs = cs; ba = ca; break; } else if (cs > s && (cs < bs || bi == -1)) { bi = ci; bs = cs; ba = ca; } if (bs >= s) { da = ba->diskaddr[bi]; DMnfree -= s; if (bs == s) { DMnfblks--; ba->diskaddr[bi] = -1L; } else ba->diskaddr[bi] += s; ba->nfree[bi] -= s; } } if (da == -1L) { long sw; if (-1L == lseek(DMhandle, 0L, SEEK_END)) error(fun, "lseek"); if ((long) s != (sw = longwrite(DMhandle, buf, (long) s))) /* by checking DMflist I know that d_compact1 will not rmalloc which is something disk_next must NEVER do */ if (rtf && DMflist) { long ta = DMnext; int add; if (sw != -1L) { DMnext += sw; add = free_disk((MAX_SIZ_TYP) sw, ta, 1); } d_compact1(); if (sw != -1L && add) if (free_disk((MAX_SIZ_TYP) sw, ta, 1)) error(fun, "internal"); rtf = 0; goto retry; } else error(fun, "write"); DMneedflg = 1; /* I had to extend the swap file to meet system needs */ da = DMnext; DMnext += s; } else { DMneedflg = 0; /* no need to extend swap file */ if (-1L == lseek(DMhandle, da, SEEK_SET)) error(fun, "lseek"); if ((long) s != longwrite(DMhandle, buf, (long) s)) error(fun, "write"); } return(da); }
/* * main() - loop forever, reading the hdaps values and * parking/unparking as necessary */ int main (int argc, char** argv) { struct utsname sysinfo; struct list *p = NULL; int c, park_now, protect_factor; int x = 0, y = 0, z = 0; int fd, i, ret, threshold = 15, adaptive = 0, pidfile = 0, parked = 0, forceadd = 0; double unow = 0, parked_utime = 0; struct option longopts[] = { {"device", required_argument, NULL, 'd'}, {"sensitivity", required_argument, NULL, 's'}, {"adaptive", no_argument, NULL, 'a'}, {"verbose", no_argument, NULL, 'v'}, {"background", no_argument, NULL, 'b'}, {"pidfile", optional_argument, NULL, 'p'}, {"dry-run", no_argument, NULL, 't'}, {"poll-sysfs", no_argument, NULL, 'y'}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {"syslog", no_argument, NULL, 'l'}, {"force", no_argument, NULL, 'f'}, {NULL, 0, NULL, 0} }; if (uname(&sysinfo) < 0 || strcmp("2.6.27", sysinfo.release) <= 0) { protect_factor = 1000; kernel_interface = UNLOAD_HEADS; } else { protect_factor = 1; kernel_interface = PROTECT; } openlog(PACKAGE_NAME, LOG_PID, LOG_DAEMON); while ((c = getopt_long(argc, argv, "d:s:vbap::tyVhlf", longopts, NULL)) != -1) { switch (c) { case 'd': add_disk(optarg); break; case 's': threshold = atoi(optarg); break; case 'b': background = 1; break; case 'a': adaptive = 1; break; case 'v': verbose = 1; break; case 'p': pidfile = 1; if (optarg == NULL) { snprintf(pid_file, sizeof(pid_file), "%s", PID_FILE); } else { snprintf(pid_file, sizeof(pid_file), "%s", optarg); } break; case 't': printlog(stdout, "Dry run, will not actually park heads or freeze queue."); dry_run = 1; break; case 'y': poll_sysfs = 1; break; case 'V': version(); break; case 'l': dosyslog = 1; break; case 'f': forceadd = 1; break; case 'h': default: usage(); break; } } printlog(stdout, "Starting "PACKAGE_NAME); if (disklist && forceadd) { char protect_method[FILENAME_MAX] = ""; p = disklist; while (p != NULL) { snprintf(protect_method, sizeof(protect_method), QUEUE_METHOD_FMT, p->name); if (kernel_interface == UNLOAD_HEADS) fd = open (p->protect_file, O_RDWR); else fd = open (protect_method, O_RDWR); if (fd > 0) { if (kernel_interface == UNLOAD_HEADS) ret = write(fd, FORCE_UNLOAD_HEADS, strlen(FORCE_UNLOAD_HEADS)); else ret = write(fd, FORCE_PROTECT_METHOD, strlen(FORCE_PROTECT_METHOD)); if (ret == -1) printlog(stderr, "Could not forcely enable UNLOAD feature for %s", p->name); else printlog(stdout, "Forcely enabled UNLOAD for %s", p->name); close(fd); } else printlog(stderr, "Could not open %s for forcely enabling UNLOAD feature", p->protect_file); p = p->next; } } if (disklist == NULL) { printlog(stdout, "WARNING: You did not supply any devices to protect, trying autodetection."); if (autodetect_devices() < 1) printlog(stderr, "Could not detect any devices."); } if (disklist == NULL) usage(argv); /* Let's see if we're on a ThinkPad or on an *Book */ select_interface(0); if (!position_interface) select_interface(1); if (!position_interface) { printlog(stdout, "Could not find a suitable interface"); return -1; } else printlog(stdout, "Selected interface: %s", interface_names[position_interface]); if (!poll_sysfs) { if (position_interface == INTERFACE_HDAPS) { hdaps_input_nr = device_find_byphys("hdaps/input1"); hdaps_input_fd = device_open(hdaps_input_nr); if (hdaps_input_fd < 0) { printlog(stdout, "WARNING: Could not find hdaps input device (%s). " "You may be using an incompatible version of the hdaps module. " "Falling back to reading the position from sysfs (uses more power).\n" "Use '-y' to silence this warning.", strerror(errno)); poll_sysfs = 1; } else { printlog(stdout, "Selected HDAPS input device: /dev/input/event%d", hdaps_input_nr); } } else if (position_interface == INTERFACE_AMS) { hdaps_input_nr = device_find_byname("Apple Motion Sensor"); hdaps_input_fd = device_open(hdaps_input_nr); if (hdaps_input_fd < 0) { printlog(stdout, "WARNING: Could not find AMS input device, do you need to set joystick=1?"); poll_sysfs = 1; } else { printlog(stdout, "Selected AMS input device /dev/input/event%d", hdaps_input_nr); } } } if (background) { verbose = 0; if (pidfile) { fd = open (pid_file, O_WRONLY | O_CREAT, 0644); if (fd < 0) { printlog (stderr, "Could not create pidfile: %s", pid_file); return 1; } } daemon(0,0); if (pidfile) { char buf[BUF_LEN]; snprintf (buf, sizeof(buf), "%d\n", getpid()); ret = write (fd, buf, strlen(buf)); if (ret < 0) { printlog (stderr, "Could not write to pidfile %s", pid_file); return 1; } if (close (fd)) { printlog (stderr, "Could not close pidfile %s", pid_file); return 1; } } } mlockall(MCL_FUTURE); if (verbose) { p = disklist; while (p != NULL) { printf("disk: %s\n", p->name); p = p->next; } printf("threshold: %i\n", threshold); printf("read_method: %s\n", poll_sysfs ? "poll-sysfs" : "input-dev"); } /* check the protect attribute exists */ /* wait for it if it's not there (in case the attribute hasn't been created yet) */ p = disklist; while (p != NULL && !dry_run) { fd = open (p->protect_file, O_RDWR); if (background) for (i = 0; fd < 0 && i < 100; ++i) { usleep (100000); /* 10 Hz */ fd = open (p->protect_file, O_RDWR); } if (fd < 0) { printlog (stderr, "Could not open %s\nDoes your kernel/drive support IDLE_IMMEDIATE with UNLOAD?", p->protect_file); free_disk(disklist); return 1; } close (fd); p = p->next; } /* see if we can read the sensor */ /* wait for it if it's not there (in case the attribute hasn't been created yet) */ ret = read_position_from_sysfs (&x, &y, &z); if (background) for (i = 0; ret && i < 100; ++i) { usleep (100000); /* 10 Hz */ ret = read_position_from_sysfs (&x, &y, &z); } if (ret) { printlog(stderr, "Could not read position from sysfs."); return 1; } /* adapt to the driver's sampling rate */ if (position_interface == INTERFACE_HDAPS) sampling_rate = read_int(SAMPLING_RATE_FILE); if (sampling_rate <= 0) sampling_rate = DEFAULT_SAMPLING_RATE; if (verbose) printf("sampling_rate: %d\n", sampling_rate); signal(SIGUSR1, SIGUSR1_handler); signal(SIGTERM, SIGTERM_handler); while (running) { if (poll_sysfs) { usleep (1000000/sampling_rate); ret = read_position_from_sysfs (&x, &y, &z); unow = get_utime(); /* microsec */ } else { double oldunow = unow; int oldx = x, oldy = y, oldz = z; ret = read_position_from_inputdev (&x, &y, &z, &unow); /* The input device issues events only when the position changed. * The analysis state needs to know how long the position remained * unchanged, so send analyze() a fake retroactive update before sending * the new one. */ if (!ret && oldunow && unow-oldunow > 1.5/sampling_rate) analyze(oldx, oldy, unow-1.0/sampling_rate, threshold, adaptive, parked); } if (ret) { if (verbose) printf("readout error (%d)\n", ret); continue; } park_now = analyze(x, y, unow, threshold, adaptive, parked); if (park_now && !pause_now) { if (!parked || unow>parked_utime+REFREEZE_SECONDS) { /* Not frozen or freeze about to expire */ p = disklist; while (p != NULL) { write_protect(p->protect_file, (FREEZE_SECONDS+FREEZE_EXTRA_SECONDS) * protect_factor); p = p->next; } /* Write protect before any output (xterm, or * whatever else is handling our stdout, may be * swapped out). */ if (!parked) printlog(stdout, "parking"); parked = 1; parked_utime = unow; } } else { if (parked && (pause_now || unow>parked_utime+FREEZE_SECONDS)) { /* Sanity check */ p = disklist; while (p != NULL) { if (!dry_run && !read_int(p->protect_file)) printlog(stderr, "Error! Not parked when we " "thought we were... (paged out " "and timer expired?)"); /* Freeze has expired */ write_protect(p->protect_file, 0); /* unprotect */ p = p->next; } parked = 0; printlog(stdout, "un-parking"); } while (pause_now) { pause_now = 0; printlog(stdout, "pausing for %d seconds", SIGUSR1_SLEEP_SEC); sleep(SIGUSR1_SLEEP_SEC); } } } free_disk(disklist); printlog(stdout, "Terminating "PACKAGE_NAME); closelog(); if (pidfile) unlink(pid_file); munlockall(); return ret; }