Merge "File header cleanup."
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 @@
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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 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 @@
{ "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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 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_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
similarity index 100%
rename from include/pixelflinger/format.h
rename to libpixelflinger/include/pixelflinger/format.h
diff --git a/include/pixelflinger/pixelflinger.h b/libpixelflinger/include/pixelflinger/pixelflinger.h
similarity index 100%
rename from include/pixelflinger/pixelflinger.h
rename to libpixelflinger/include/pixelflinger/pixelflinger.h
diff --git a/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h
similarity index 100%
rename from include/private/pixelflinger/ggl_context.h
rename to libpixelflinger/include/private/pixelflinger/ggl_context.h
diff --git a/include/private/pixelflinger/ggl_fixed.h b/libpixelflinger/include/private/pixelflinger/ggl_fixed.h
similarity index 100%
rename from include/private/pixelflinger/ggl_fixed.h
rename to 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 @@
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_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 @@
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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
-}