diff options
20 files changed, 132 insertions, 473 deletions
diff --git a/adb/.clang-format b/adb/.clang-format index 2b83a1f..0395c8e 100644 --- a/adb/.clang-format +++ b/adb/.clang-format @@ -4,8 +4,8 @@ AllowShortFunctionsOnASingleLine: false CommentPragmas: NOLINT:.* DerivePointerAlignment: false -IndentWidth: 2 +IndentWidth: 4 PointerAlignment: Left -TabWidth: 2 +TabWidth: 4 UseTab: Never PenaltyExcessCharacter: 32 diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 9cb002f..b9e957f 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -23,7 +23,7 @@ LOCAL_SRC_FILES := protocol.c engine.c bootimg_utils.cpp fastboot.cpp util.c fs. LOCAL_MODULE := fastboot LOCAL_MODULE_TAGS := debug LOCAL_CONLYFLAGS += -std=gnu99 -LOCAL_CFLAGS += -Wall -Werror +LOCAL_CFLAGS += -Wall -Wextra -Werror ifeq ($(HOST_OS),linux) LOCAL_SRC_FILES += usb_linux.c util_linux.c @@ -53,9 +53,11 @@ endif LOCAL_STATIC_LIBRARIES := \ $(EXTRA_STATIC_LIBS) \ - libzipfile \ + libziparchive-host \ libext4_utils_host \ libsparse_host \ + libutils \ + liblog \ libz ifneq ($(HOST_OS),windows) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 04f3166..6dc7d34 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -45,7 +45,7 @@ #include <unistd.h> #include <sparse/sparse.h> -#include <zipfile/zipfile.h> +#include <ziparchive/zip_archive.h> #include "bootimg_utils.h" #include "fastboot.h" @@ -379,30 +379,26 @@ void *load_bootable_image(const char *kernel, const char *ramdisk, return bdata; } -static void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) +static void* unzip_file(ZipArchiveHandle zip, const char* entry_name, unsigned* sz) { - void *data; - zipentry_t entry; - unsigned datasz; - - entry = lookup_zipentry(zip, name); - if (entry == NULL) { - fprintf(stderr, "archive does not contain '%s'\n", name); + ZipEntryName zip_entry_name(entry_name); + ZipEntry zip_entry; + if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) { + fprintf(stderr, "archive does not contain '%s'\n", entry_name); return 0; } - *sz = get_zipentry_size(entry); + *sz = zip_entry.uncompressed_length; - datasz = *sz * 1.001; - data = malloc(datasz); - - if(data == 0) { - fprintf(stderr, "failed to allocate %d bytes\n", *sz); + uint8_t* data = reinterpret_cast<uint8_t*>(malloc(zip_entry.uncompressed_length)); + if (data == NULL) { + fprintf(stderr, "failed to allocate %u bytes for '%s'\n", *sz, entry_name); return 0; } - if (decompress_zipentry(entry, data, datasz)) { - fprintf(stderr, "failed to unzip '%s' from archive\n", name); + int error = ExtractToMemory(zip, &zip_entry, data, zip_entry.uncompressed_length); + if (error != 0) { + fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error)); free(data); return 0; } @@ -410,24 +406,28 @@ static void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) return data; } -static int unzip_to_file(zipfile_t zip, char *name) -{ - int fd = fileno(tmpfile()); - if (fd < 0) { +static int unzip_to_file(ZipArchiveHandle zip, char* entry_name) { + FILE* fp = tmpfile(); + if (fp == NULL) { + fprintf(stderr, "failed to create temporary file for '%s': %s\n", + entry_name, strerror(errno)); return -1; } - unsigned sz; - void* data = unzip_file(zip, name, &sz); - if (data == 0) { + ZipEntryName zip_entry_name(entry_name); + ZipEntry zip_entry; + if (FindEntry(zip, zip_entry_name, &zip_entry) != 0) { + fprintf(stderr, "archive does not contain '%s'\n", entry_name); return -1; } - if (write(fd, data, sz) != (ssize_t)sz) { - fd = -1; + int fd = fileno(fp); + int error = ExtractEntryToFile(zip, &zip_entry, fd); + if (error != 0) { + fprintf(stderr, "failed to extract '%s': %s\n", entry_name, ErrorCodeString(error)); + return -1; } - free(data); lseek(fd, 0, SEEK_SET); return fd; } @@ -693,11 +693,10 @@ void do_flash(usb_handle *usb, const char *pname, const char *fname) flash_buf(pname, &buf); } -void do_update_signature(zipfile_t zip, char *fn) +void do_update_signature(ZipArchiveHandle zip, char *fn) { - void *data; unsigned sz; - data = unzip_file(zip, fn, &sz); + void* data = unzip_file(zip, fn, &sz); if (data == 0) return; fb_queue_download("signature", data, sz); fb_queue_command("signature", "installing signature"); @@ -709,23 +708,16 @@ void do_update(usb_handle *usb, const char *filename, int erase_first) fb_queue_query_save("product", cur_product, sizeof(cur_product)); - unsigned zsize; - void* zdata = load_file(filename, &zsize); - if (zdata == 0) die("failed to load '%s': %s", filename, strerror(errno)); - - zipfile_t zip = init_zipfile(zdata, zsize); - if (zip == 0) die("failed to access zipdata in '%s'"); + ZipArchiveHandle zip; + int error = OpenArchive(filename, &zip); + if (error != 0) { + die("failed to open zip file '%s': %s", filename, ErrorCodeString(error)); + } unsigned sz; void* data = unzip_file(zip, "android-info.txt", &sz); if (data == 0) { - /* fallback for older zipfiles */ - data = unzip_file(zip, "android-product.txt", &sz); - if ((data == 0) || (sz < 1)) { - die("update package has no android-info.txt or android-product.txt"); - } - data = mkmsg("board=%sversion-baseband=0.66.04.19\n", reinterpret_cast<char*>(data)); - sz = strlen(reinterpret_cast<char*>(data)); + die("update package '%s' has no android-info.txt", filename); } setup_requirements(reinterpret_cast<char*>(data), sz); @@ -750,6 +742,8 @@ void do_update(usb_handle *usb, const char *filename, int erase_first) * program exits. */ } + + CloseArchive(zip); } void do_send_signature(char *fn) diff --git a/fastboot/protocol.c b/fastboot/protocol.c index 10a84c1..5b97600 100644 --- a/fastboot/protocol.c +++ b/fastboot/protocol.c @@ -305,7 +305,10 @@ int fb_download_data_sparse(usb_handle *usb, struct sparse_file *s) return -1; } - fb_download_data_sparse_flush(usb); + r = fb_download_data_sparse_flush(usb); + if (r < 0) { + return -1; + } return _command_end(usb); } diff --git a/init/init.cpp b/init/init.cpp index e1c82a4..5a40fd3 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -15,6 +15,7 @@ */ #include <ctype.h> +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <libgen.h> @@ -40,6 +41,8 @@ #include <selinux/label.h> #include <selinux/android.h> +#include <base/file.h> +#include <base/stringprintf.h> #include <cutils/android_reboot.h> #include <cutils/fs.h> #include <cutils/iosched_policy.h> @@ -47,6 +50,8 @@ #include <cutils/sockets.h> #include <private/android_filesystem_config.h> +#include <memory> + #include "devices.h" #include "init.h" #include "log.h" @@ -66,8 +71,6 @@ static int property_triggers_enabled = 0; static char console[32]; static char bootmode[32]; -static char hardware[32]; -static unsigned revision = 0; static char qemu[32]; static struct action *cur_action = NULL; @@ -773,6 +776,8 @@ static void export_kernel_boot_props(void) { "ro.boot.mode", "ro.bootmode", "unknown", }, { "ro.boot.baseband", "ro.baseband", "unknown", }, { "ro.boot.bootloader", "ro.bootloader", "unknown", }, + { "ro.boot.hardware", "ro.hardware", "unknown", }, + { "ro.boot.revision", "ro.revision", "0", }, }; for (i = 0; i < ARRAY_SIZE(prop_map); i++) { @@ -791,16 +796,6 @@ static void export_kernel_boot_props(void) property_get("ro.bootmode", tmp); strlcpy(bootmode, tmp, sizeof(bootmode)); - /* if this was given on kernel command line, override what we read - * before (e.g. from /proc/cpuinfo), if anything */ - ret = property_get("ro.boot.hardware", tmp); - if (ret) - strlcpy(hardware, tmp, sizeof(hardware)); - property_set("ro.hardware", hardware); - - snprintf(tmp, PROP_VALUE_MAX, "%d", revision); - property_set("ro.revision", tmp); - /* TODO: these are obsolete. We should delete them */ if (!strcmp(bootmode,"factory")) property_set("ro.factorytest", "1"); @@ -810,6 +805,40 @@ static void export_kernel_boot_props(void) property_set("ro.factorytest", "0"); } +static void process_kernel_dt(void) +{ + static const char android_dir[] = "/proc/device-tree/firmware/android"; + + std::string file_name = android::base::StringPrintf("%s/compatible", android_dir); + + std::string dt_file; + android::base::ReadFileToString(file_name, &dt_file); + if (!dt_file.compare("android,firmware")) { + ERROR("firmware/android is not compatible with 'android,firmware'\n"); + return; + } + + std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(android_dir), closedir); + if (!dir) + return; + + struct dirent *dp; + while ((dp = readdir(dir.get())) != NULL) { + if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible")) + continue; + + file_name = android::base::StringPrintf("%s/%s", android_dir, dp->d_name); + + android::base::ReadFileToString(file_name, &dt_file); + std::replace(dt_file.begin(), dt_file.end(), ',', '.'); + + std::string property_name = android::base::StringPrintf("ro.boot.%s", dp->d_name); + if (property_set(property_name.c_str(), dt_file.c_str())) { + ERROR("Could not set property %s to value %s", property_name.c_str(), dt_file.c_str()); + } + } +} + static void process_kernel_cmdline(void) { /* don't expose the raw commandline to nonpriv processes */ @@ -822,11 +851,6 @@ static void process_kernel_cmdline(void) import_kernel_cmdline(0, import_kernel_nv); if (qemu[0]) import_kernel_cmdline(1, import_kernel_nv); - - /* now propogate the info given on command line to internal variables - * used by init as well as the current required properties - */ - export_kernel_boot_props(); } static int property_service_init_action(int nargs, char **args) @@ -1014,10 +1038,17 @@ int main(int argc, char** argv) { klog_init(); property_init(); - get_hardware_name(hardware, &revision); - + process_kernel_dt(); + /* in case one is passing arguments both on the command line and in DT + * Properties set in DT always have priority over the command-line ones + */ process_kernel_cmdline(); + /* now propogate the kernel variables to internal variables + * used by init as well as the current required properties + */ + export_kernel_boot_props(); + selinux_callback cb; cb.func_log = log_callback; selinux_set_callback(SELINUX_CB_LOG, cb); diff --git a/init/ueventd.cpp b/init/ueventd.cpp index d56b91a..5af6e3d 100644 --- a/init/ueventd.cpp +++ b/init/ueventd.cpp @@ -30,28 +30,13 @@ #include "util.h" #include "devices.h" #include "ueventd_parser.h" - -static char hardware[32]; -static unsigned revision = 0; - -static void import_kernel_nv(char *name, int in_qemu) -{ - if (*name != '\0') { - char *value = strchr(name, '='); - if (value != NULL) { - *value++ = 0; - if (!strcmp(name,"androidboot.hardware")) - { - strlcpy(hardware, value, sizeof(hardware)); - } - } - } -} +#include "property_service.h" int ueventd_main(int argc, char **argv) { struct pollfd ufd; int nr; + char hardware[PROP_VALUE_MAX]; char tmp[32]; /* @@ -83,12 +68,7 @@ int ueventd_main(int argc, char **argv) INFO("starting ueventd\n"); - /* Respect hardware passed in through the kernel cmd line. Here we will look - * for androidboot.hardware param in kernel cmdline, and save its value in - * hardware[]. */ - import_kernel_cmdline(0, import_kernel_nv); - - get_hardware_name(hardware, &revision); + property_get("ro.hardware", hardware); ueventd_parse_config_file("/ueventd.rc"); diff --git a/init/util.cpp b/init/util.cpp index c805083..8b238d4 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -400,39 +400,6 @@ void open_devnull_stdio(void) exit(1); } -void get_hardware_name(char *hardware, unsigned int *revision) { - // Hardware string was provided on kernel command line. - if (hardware[0]) { - return; - } - - FILE* fp = fopen("/proc/cpuinfo", "re"); - if (fp == NULL) { - return; - } - char buf[1024]; - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (strncmp(buf, "Hardware", 8) == 0) { - const char* hw = strstr(buf, ": "); - if (hw) { - hw += 2; - size_t n = 0; - while (*hw) { - if (!isspace(*hw)) { - hardware[n++] = tolower(*hw); - } - hw++; - if (n == 31) break; - } - hardware[n] = 0; - } - } else if (strncmp(buf, "Revision", 8) == 0) { - sscanf(buf, "Revision : %ux", revision); - } - } - fclose(fp); -} - void import_kernel_cmdline(int in_qemu, void (*import_kernel_nv)(char *name, int in_qemu)) { diff --git a/init/util.h b/init/util.h index 77da3ac..e0b3c69 100644 --- a/init/util.h +++ b/init/util.h @@ -42,7 +42,6 @@ void make_link(const char *oldpath, const char *newpath); void remove_link(const char *oldpath, const char *newpath); int wait_for_file(const char *filename, int timeout); void open_devnull_stdio(void); -void get_hardware_name(char *hardware, unsigned int *revision); void import_kernel_cmdline(int in_qemu, void (*import_kernel_nv)(char *name, int in_qemu)); int make_dir(const char *path, mode_t mode); int restorecon(const char *pathname); diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk index aa614bc..697db25 100644 --- a/libpixelflinger/Android.mk +++ b/libpixelflinger/Android.mk @@ -62,6 +62,8 @@ LOCAL_SRC_FILES_arm := $(PIXELFLINGER_SRC_FILES_arm) LOCAL_SRC_FILES_arm64 := $(PIXELFLINGER_SRC_FILES_arm64) LOCAL_SRC_FILES_mips := $(PIXELFLINGER_SRC_FILES_mips) LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include +LOCAL_C_INCLUDES += $(LOCAL_EXPORT_C_INCLUDE_DIRS) LOCAL_SHARED_LIBRARIES := libcutils liblog # Really this should go away entirely or at least not depend on diff --git a/include/pixelflinger/format.h b/libpixelflinger/include/pixelflinger/format.h index 82eeca4..82eeca4 100644 --- a/include/pixelflinger/format.h +++ b/libpixelflinger/include/pixelflinger/format.h diff --git a/include/pixelflinger/pixelflinger.h b/libpixelflinger/include/pixelflinger/pixelflinger.h index 8a2b442..8a2b442 100644 --- a/include/pixelflinger/pixelflinger.h +++ b/libpixelflinger/include/pixelflinger/pixelflinger.h diff --git a/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h index d43655c..d43655c 100644 --- a/include/private/pixelflinger/ggl_context.h +++ b/libpixelflinger/include/private/pixelflinger/ggl_context.h diff --git a/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h index 787f620..787f620 100644 --- a/include/private/pixelflinger/ggl_fixed.h +++ b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h diff --git a/libpixelflinger/tests/arch-arm64/assembler/Android.mk b/libpixelflinger/tests/arch-arm64/assembler/Android.mk index 961f323..448d298 100644 --- a/libpixelflinger/tests/arch-arm64/assembler/Android.mk +++ b/libpixelflinger/tests/arch-arm64/assembler/Android.mk @@ -13,7 +13,7 @@ LOCAL_SHARED_LIBRARIES := \ libpixelflinger LOCAL_C_INCLUDES := \ - system/core/libpixelflinger + $(LOCAL_PATH)/../../.. LOCAL_MODULE:= test-pixelflinger-arm64-assembler-test diff --git a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk b/libpixelflinger/tests/arch-arm64/disassembler/Android.mk index 8f62f09..d8f7e69 100644 --- a/libpixelflinger/tests/arch-arm64/disassembler/Android.mk +++ b/libpixelflinger/tests/arch-arm64/disassembler/Android.mk @@ -7,9 +7,6 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := -LOCAL_C_INCLUDES := \ - system/core/libpixelflinger/codeflinger - LOCAL_MODULE:= test-pixelflinger-arm64-disassembler-test LOCAL_MODULE_TAGS := tests diff --git a/libpixelflinger/tests/codegen/Android.mk b/libpixelflinger/tests/codegen/Android.mk index bc07015..2f9ca2f 100644 --- a/libpixelflinger/tests/codegen/Android.mk +++ b/libpixelflinger/tests/codegen/Android.mk @@ -9,7 +9,7 @@ LOCAL_SHARED_LIBRARIES := \ libpixelflinger LOCAL_C_INCLUDES := \ - system/core/libpixelflinger + $(LOCAL_PATH)/../.. LOCAL_MODULE:= test-opengl-codegen diff --git a/libpixelflinger/tests/gglmul/Android.mk b/libpixelflinger/tests/gglmul/Android.mk index f479fa1..75bd39e 100644 --- a/libpixelflinger/tests/gglmul/Android.mk +++ b/libpixelflinger/tests/gglmul/Android.mk @@ -7,7 +7,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := LOCAL_C_INCLUDES := \ - system/core/libpixelflinger + $(LOCAL_PATH)/../../include LOCAL_MODULE:= test-pixelflinger-gglmul diff --git a/libsparse/sparse.c b/libsparse/sparse.c index baa30cd..65c09e0 100644 --- a/libsparse/sparse.c +++ b/libsparse/sparse.c @@ -101,26 +101,32 @@ unsigned int sparse_count_chunks(struct sparse_file *s) return chunks; } -static void sparse_file_write_block(struct output_file *out, +static int sparse_file_write_block(struct output_file *out, struct backed_block *bb) { + int ret = -EINVAL; + switch (backed_block_type(bb)) { case BACKED_BLOCK_DATA: - write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); + ret = write_data_chunk(out, backed_block_len(bb), backed_block_data(bb)); break; case BACKED_BLOCK_FILE: - write_file_chunk(out, backed_block_len(bb), - backed_block_filename(bb), backed_block_file_offset(bb)); + ret = write_file_chunk(out, backed_block_len(bb), + backed_block_filename(bb), + backed_block_file_offset(bb)); break; case BACKED_BLOCK_FD: - write_fd_chunk(out, backed_block_len(bb), - backed_block_fd(bb), backed_block_file_offset(bb)); + ret = write_fd_chunk(out, backed_block_len(bb), + backed_block_fd(bb), + backed_block_file_offset(bb)); break; case BACKED_BLOCK_FILL: - write_fill_chunk(out, backed_block_len(bb), - backed_block_fill_val(bb)); + ret = write_fill_chunk(out, backed_block_len(bb), + backed_block_fill_val(bb)); break; } + + return ret; } static int write_all_blocks(struct sparse_file *s, struct output_file *out) @@ -128,6 +134,7 @@ static int write_all_blocks(struct sparse_file *s, struct output_file *out) struct backed_block *bb; unsigned int last_block = 0; int64_t pad; + int ret = 0; for (bb = backed_block_iter_new(s->backed_block_list); bb; bb = backed_block_iter_next(bb)) { @@ -135,7 +142,9 @@ static int write_all_blocks(struct sparse_file *s, struct output_file *out) unsigned int blocks = backed_block_block(bb) - last_block; write_skip_chunk(out, (int64_t)blocks * s->block_size); } - sparse_file_write_block(out, bb); + ret = sparse_file_write_block(out, bb); + if (ret) + return ret; last_block = backed_block_block(bb) + DIV_ROUND_UP(backed_block_len(bb), s->block_size); } @@ -230,6 +239,7 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, struct backed_block *bb; struct backed_block *start; int64_t file_len = 0; + int ret; /* * overhead is sparse file header, initial skip chunk, split chunk, end @@ -249,7 +259,11 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, for (bb = start; bb; bb = backed_block_iter_next(bb)) { count = 0; /* will call out_counter_write to update count */ - sparse_file_write_block(out_counter, bb); + ret = sparse_file_write_block(out_counter, bb); + if (ret) { + bb = NULL; + goto out; + } if (file_len + count > len) { /* * If the remaining available size is more than 1/8th of the @@ -260,16 +274,17 @@ static struct backed_block *move_chunks_up_to_len(struct sparse_file *from, backed_block_split(from->backed_block_list, bb, len - file_len); last_bb = bb; } - goto out; + goto move; } file_len += count; last_bb = bb; } -out: +move: backed_block_list_move(from->backed_block_list, to->backed_block_list, start, last_bb); +out: output_file_close(out_counter); return bb; diff --git a/toolbox/Android.mk b/toolbox/Android.mk index b822ea0..959dc22 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -60,7 +60,6 @@ OUR_TOOLS := \ restorecon \ route \ runcon \ - schedtop \ sendevent \ setprop \ start \ diff --git a/toolbox/schedtop.c b/toolbox/schedtop.c deleted file mode 100644 index 2fccd2e..0000000 --- a/toolbox/schedtop.c +++ /dev/null @@ -1,330 +0,0 @@ -#include <ctype.h> -#include <dirent.h> -#include <fcntl.h> -#include <pwd.h> -#include <signal.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -struct thread_info { - int pid; - int tid; - char name[64]; - unsigned long long exec_time; - unsigned long long delay_time; - unsigned long long run_count; -}; - -struct thread_table { - size_t allocated; - size_t active; - struct thread_info *data; -}; - -enum { - FLAG_BATCH = 1U << 0, - FLAG_HIDE_IDLE = 1U << 1, - FLAG_SHOW_THREADS = 1U << 2, - FLAG_USE_ALTERNATE_SCREEN = 1U << 3, -}; - -static int time_dp = 9; -static int time_div = 1; -#define NS_TO_S_D(ns) \ - (uint32_t)((ns) / 1000000000), time_dp, ((uint32_t)((ns) % 1000000000) / time_div) - -struct thread_table processes; -struct thread_table last_processes; -struct thread_table threads; -struct thread_table last_threads; - -static void grow_table(struct thread_table *table) -{ - size_t size = table->allocated; - struct thread_info *new_table; - if (size < 128) - size = 128; - else - size *= 2; - - new_table = realloc(table->data, size * sizeof(*table->data)); - if (new_table == NULL) { - fprintf(stderr, "out of memory\n"); - exit(1); - } - table->data = new_table; - table->allocated = size; -} - -static struct thread_info *get_item(struct thread_table *table) -{ - if (table->active >= table->allocated) - grow_table(table); - return table->data + table->active; -} - -static void commit_item(struct thread_table *table) -{ - table->active++; -} - -static int read_line(char *line, size_t line_size) -{ - int fd; - int len; - fd = open(line, O_RDONLY); - if(fd == 0) - return -1; - len = read(fd, line, line_size - 1); - close(fd); - if (len <= 0) - return -1; - line[len] = '\0'; - return 0; -} - -static void add_thread(int pid, int tid, struct thread_info *proc_info) -{ - char line[1024]; - char *name, *name_end; - size_t name_len; - struct thread_info *info; - if(tid == 0) - info = get_item(&processes); - else - info = get_item(&threads); - info->pid = pid; - info->tid = tid; - - if(tid) - sprintf(line, "/proc/%d/task/%d/schedstat", pid, tid); - else - sprintf(line, "/proc/%d/schedstat", pid); - if (read_line(line, sizeof(line))) - return; - if(sscanf(line, "%llu %llu %llu", - &info->exec_time, &info->delay_time, &info->run_count) != 3) - return; - if (proc_info) { - proc_info->exec_time += info->exec_time; - proc_info->delay_time += info->delay_time; - proc_info->run_count += info->run_count; - } - - name = NULL; - if (!tid) { - sprintf(line, "/proc/%d/cmdline", pid); - if (read_line(line, sizeof(line)) == 0 && line[0]) { - name = line; - name_len = strlen(name); - } - } - if (!name) { - if (tid) - sprintf(line, "/proc/%d/task/%d/stat", pid, tid); - else - sprintf(line, "/proc/%d/stat", pid); - if (read_line(line, sizeof(line))) - return; - name = strchr(line, '('); - if (name == NULL) - return; - name_end = strchr(name, ')'); - if (name_end == NULL) - return; - name++; - name_len = name_end - name; - } - if (name_len >= sizeof(info->name)) - name_len = sizeof(info->name) - 1; - memcpy(info->name, name, name_len); - info->name[name_len] = '\0'; - if(tid == 0) - commit_item(&processes); - else - commit_item(&threads); -} - -static void add_threads(int pid, struct thread_info *proc_info) -{ - char path[1024]; - DIR *d; - struct dirent *de; - sprintf(path, "/proc/%d/task", pid); - d = opendir(path); - if(d == 0) return; - while((de = readdir(d)) != 0){ - if(isdigit(de->d_name[0])){ - int tid = atoi(de->d_name); - add_thread(pid, tid, proc_info); - } - } - closedir(d); -} - -static void print_threads(int pid, uint32_t flags) -{ - size_t i, j; - for (i = 0; i < last_threads.active; i++) { - int epid = last_threads.data[i].pid; - int tid = last_threads.data[i].tid; - if (epid != pid) - continue; - for (j = 0; j < threads.active; j++) - if (tid == threads.data[j].tid) - break; - if (j == threads.active) - printf(" %5u died\n", tid); - else if (!(flags & FLAG_HIDE_IDLE) || threads.data[j].run_count - last_threads.data[i].run_count) - printf(" %5u %2u.%0*u %2u.%0*u %5llu %5u.%0*u %5u.%0*u %7llu %s\n", tid, - NS_TO_S_D(threads.data[j].exec_time - last_threads.data[i].exec_time), - NS_TO_S_D(threads.data[j].delay_time - last_threads.data[i].delay_time), - threads.data[j].run_count - last_threads.data[i].run_count, - NS_TO_S_D(threads.data[j].exec_time), NS_TO_S_D(threads.data[j].delay_time), - threads.data[j].run_count, threads.data[j].name); - } -} - -static void update_table(DIR *d, uint32_t flags) -{ - size_t i, j; - struct dirent *de; - - rewinddir(d); - while((de = readdir(d)) != 0){ - if(isdigit(de->d_name[0])){ - int pid = atoi(de->d_name); - struct thread_info *proc_info; - add_thread(pid, 0, NULL); - proc_info = &processes.data[processes.active - 1]; - proc_info->exec_time = 0; - proc_info->delay_time = 0; - proc_info->run_count = 0; - add_threads(pid, proc_info); - } - } - if (!(flags & FLAG_BATCH)) - printf("\e[H\e[0J"); - printf("Processes: %zu, Threads %zu\n", processes.active, threads.active); - switch (time_dp) { - case 3: - printf(" TID --- SINCE LAST ---- ---------- TOTAL ----------\n"); - printf(" PID EXEC_T DELAY SCHED EXEC_TIME DELAY_TIM SCHED NAME\n"); - break; - case 6: - printf(" TID ------ SINCE LAST ------- ------------ TOTAL -----------\n"); - printf(" PID EXEC_TIME DELAY_TIM SCHED EXEC_TIME DELAY_TIME SCHED NAME\n"); - break; - default: - printf(" TID -------- SINCE LAST -------- ------------- TOTAL -------------\n"); - printf(" PID EXEC_TIME DELAY_TIME SCHED EXEC_TIME DELAY_TIME SCHED NAME\n"); - break; - } - for (i = 0; i < last_processes.active; i++) { - int pid = last_processes.data[i].pid; - for (j = 0; j < processes.active; j++) - if (pid == processes.data[j].pid) - break; - if (j == processes.active) - printf("%5u died\n", pid); - else if (!(flags & FLAG_HIDE_IDLE) || processes.data[j].run_count - last_processes.data[i].run_count) { - printf("%5u %2u.%0*u %2u.%0*u %5llu %5u.%0*u %5u.%0*u %7llu %s\n", pid, - NS_TO_S_D(processes.data[j].exec_time - last_processes.data[i].exec_time), - NS_TO_S_D(processes.data[j].delay_time - last_processes.data[i].delay_time), - processes.data[j].run_count - last_processes.data[i].run_count, - NS_TO_S_D(processes.data[j].exec_time), NS_TO_S_D(processes.data[j].delay_time), - processes.data[j].run_count, processes.data[j].name); - if (flags & FLAG_SHOW_THREADS) - print_threads(pid, flags); - } - } - - { - struct thread_table tmp; - tmp = last_processes; - last_processes = processes; - processes = tmp; - processes.active = 0; - tmp = last_threads; - last_threads = threads; - threads = tmp; - threads.active = 0; - } -} - -void -sig_abort(int signum) -{ - printf("\e[?47l"); - exit(0); -} - - -int schedtop_main(int argc, char **argv) -{ - int c; - DIR *d; - uint32_t flags = 0; - int delay = 3000000; - float delay_f; - - while(1) { - c = getopt(argc, argv, "d:ibtamun"); - if (c == EOF) - break; - switch (c) { - case 'd': - delay_f = atof(optarg); - delay = delay_f * 1000000; - break; - case 'b': - flags |= FLAG_BATCH; - break; - case 'i': - flags |= FLAG_HIDE_IDLE; - break; - case 't': - flags |= FLAG_SHOW_THREADS; - break; - case 'a': - flags |= FLAG_USE_ALTERNATE_SCREEN; - break; - case 'm': - time_dp = 3; - time_div = 1000000; - break; - case 'u': - time_dp = 6; - time_div = 1000; - break; - case 'n': - time_dp = 9; - time_div = 1; - break; - } - } - - d = opendir("/proc"); - if(d == 0) return -1; - - if (!(flags & FLAG_BATCH)) { - if(flags & FLAG_USE_ALTERNATE_SCREEN) { - signal(SIGINT, sig_abort); - signal(SIGPIPE, sig_abort); - signal(SIGTERM, sig_abort); - printf("\e7\e[?47h"); - } - printf("\e[2J"); - } - while (1) { - update_table(d, flags); - usleep(delay); - } - closedir(d); - return 0; -} |