From: William Lee Irwin III <wli@holomorphy.com>
To: mita akinobu <amgta@yacht.ocn.ne.jp>
Cc: linux-kernel@vger.kernel.org, Andries Brouwer <aeb@cwi.nl>,
Alessandro Rubini <rubini@ipvvis.unipv.it>
Subject: Re: [util-linux] readprofile ignores the last element in /proc/profile
Date: Sun, 29 Aug 2004 11:41:14 -0700 [thread overview]
Message-ID: <20040829184114.GS5492@holomorphy.com> (raw)
In-Reply-To: <20040829162252.GG5492@holomorphy.com>
[-- Attachment #1: Type: text/plain, Size: 322 bytes --]
On Sun, Aug 29, 2004 at 09:22:52AM -0700, William Lee Irwin III wrote:
> Well, since I couldn't stop vomiting for hours after I looked at the
> code for readprofile(1), here's a reimplementation, with various
> misfeatures removed, included as a MIME attachment.
I guess I might as well write a diffprof(1) too.
-- wli
[-- Attachment #2: diffprof.c --]
[-- Type: text/x-csrc, Size: 6143 bytes --]
/*
* diffprof(1) implementation.
* (C) 2004 William Irwin, Oracle
* Licensed under GPL, and derived from the following GPL code:
* linked list implementation (C) Linus Torvalds and various others
* jhash implementation (C) Bob Jenkins, David S. Miller, and others
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <limits.h>
#define TABLE_SIZE 1024
#define offsetof(type, member) ((size_t)(unsigned long)(&((type *)0)->member))
#define list_entry(elem, type, member) \
((type *)((char *)(elem) - offsetof(type, member)))
#define list_for_each(elem, list, member) \
for (elem = list_entry((list)->next, typeof(*(elem)), member); \
&(elem)->member != (list); \
elem = list_entry((elem)->member.next, typeof(*(elem)), member))
#define list_for_each_safe(elem, save, list, member) \
for (elem = list_entry((list)->next, typeof(*(elem)), member), \
save = list_entry((elem)->member.next, typeof(*(elem)), member);\
&(elem)->member != (list); \
elem = save, \
save = list_entry((save)->member.next, typeof(*(elem)), member))
/*
* A number close to ((sqrt(5) - 1)/2) * 2**32 with low d(n) (few divisors)
* 0x9e3779b9 == 2654435769 == 3 * 89 * 523 * 19009
*/
#define JHASH_GOLDEN_RATIO 0x9e3779b9
#define __jhash_mix(a, b, c) \
{ \
a -= b; a -= c; a ^= (c) >> 13; \
b -= c; b -= a; b ^= (a) << 8; \
c -= a; c -= b; c ^= (b) >> 13; \
a -= b; a -= c; a ^= (c) >> 12; \
b -= c; b -= a; b ^= (a) << 16; \
c -= a; c -= b; c ^= (b) >> 5; \
a -= b; a -= c; a ^= (c) >> 3; \
b -= c; b -= a; b ^= (a) << 10; \
c -= a; c -= b; c ^= (b) >> 15; \
}
struct list {
struct list *next, *prev;
};
struct sym {
long len, hits[2];
char *s;
struct list list;
};
static struct list table[TABLE_SIZE];
static uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
{
const uint8_t *k = key;
uint32_t a = JHASH_GOLDEN_RATIO, b = JHASH_GOLDEN_RATIO, c = initval,
len = length;
while (len >= 12) {
a += k[0] + ((uint32_t)k[1] << 8) + ((uint32_t)k[2] << 16)
+ ((uint32_t)k[3] << 24);
b += k[4] + ((uint32_t)k[5] << 8) + ((uint32_t)k[6] << 16)
+ ((uint32_t)k[7] << 24);
c += k[8] + ((uint32_t)k[9] << 8) + ((uint32_t)k[10] << 16)
+ ((uint32_t)k[11] << 24);
__jhash_mix(a,b,c);
k += 12;
len -= 12;
}
c += length;
switch (len) {
case 11:
c += (uint32_t)k[10] << 24;
case 10:
c += (uint32_t)k[9] << 16;
case 9:
c += (uint32_t)k[8] << 8;
case 8:
b += (uint32_t)k[7] << 24;
case 7:
b += (uint32_t)k[6] << 16;
case 6:
b += (uint32_t)k[5] << 8;
case 5:
b += k[4];
case 4:
a += (uint32_t)k[3] << 24;
case 3:
a += (uint32_t)k[2] << 16;
case 2:
a += (uint32_t)k[1] << 8;
case 1:
a += k[0];
}
__jhash_mix(a,b,c);
return c;
}
static void list_init(struct list *list)
{
list->next = list->prev = list;
}
static void __list_add(struct list *prev, struct list *next, struct list *elem)
{
next->prev = elem;
elem->next = next;
elem->prev = prev;
prev->next = elem;
}
static void list_add(struct list *list, struct list *elem)
{
__list_add(list, list->next, elem);
}
static void __list_del(struct list *prev, struct list *next)
{
next->prev = prev;
prev->next = next;
}
static void list_del(struct list *list)
{
__list_del(list->prev, list->next);
}
static void table_init(void)
{
int i;
for (i = 0; i < TABLE_SIZE; ++i)
list_init(&table[i]);
}
struct sym *sym_alloc(const char *buf, int after)
{
struct sym *sym = malloc(sizeof(struct sym));
if (sym) {
memset(sym, 0, sizeof(struct sym));
sym->s = strdup(buf);
if (!sym->s)
goto err_sym;
if (sscanf(buf, "%ld %s\n", &sym->hits[after], sym->s) != 2)
goto err_str;
sym->len = strlen(sym->s);
}
return sym;
err_str:
free(sym->s);
err_sym:
free(sym);
return NULL;
}
static void sym_free(struct sym *sym)
{
free(sym->s);
free(sym);
}
static void sym_emit(struct sym *sym)
{
static int digits = 0;
long difference = sym->hits[1] - sym->hits[0];
if (!digits) {
unsigned long n = ULONG_MAX;
for (n = ULONG_MAX; n >= 10; n /= 10)
++digits;
digits += !!n;
}
if (difference)
printf("%*ld %s\n", digits, difference, sym->s);
}
static void sym_hash(struct sym *sym, int after)
{
struct sym *collide;
struct list *list;
list = &table[jhash(sym->s, sym->len, sym->len) % TABLE_SIZE];
list_for_each(collide, list, list) {
if (collide->len == sym->len && !strcmp(collide->s, sym->s)) {
collide->hits[after] = sym->hits[after];
sym_emit(collide);
list_del(&collide->list);
sym_free(collide);
sym_free(sym);
return;
}
}
list_add(list, &sym->list);
}
static void sym_cleanup(void)
{
struct sym *save, *sym;
int i;
for (i = 0; i < TABLE_SIZE; ++i) {
list_for_each_safe(sym, save, &table[i], list) {
list_del(&sym->list);
sym_emit(sym);
sym_free(sym);
}
}
}
static int __read_sym(FILE *file, char **buf, size_t *bufsz, int after)
{
struct sym *sym;
ssize_t ret = getline(buf, bufsz, file);
if (ret <= 0)
return ret;
if (!(sym = sym_alloc(*buf, after)))
return -1;
sym_hash(sym, after);
return 0;
}
static void read_syms(FILE *before, FILE *after)
{
char *buf = NULL;
size_t bufsz;
int eof_before = 0, eof_after = 0;
while (!eof_before && !eof_after) {
if (!eof_before) {
if (feof(before))
eof_before = 1;
else if (__read_sym(before, &buf, &bufsz, 0) < 0)
break;
}
if (!eof_after) {
if (feof(after))
eof_after = 1;
else if (__read_sym(after, &buf, &bufsz, 1) < 0)
break;
}
}
free(buf);
}
int main(int argc, char * const argv[])
{
FILE *before, *after;
if (argc > 3 || argc < 2)
goto usage;
if (strcmp(argv[1], "-"))
before = fopen(argv[1], "r");
else {
before = stdin;
if (!strcmp(argv[2], "-"))
goto usage;
}
if (!strcmp(argv[2], "-") || argc == 2)
after = stdin;
else
after = fopen(argv[2], "r");
if (!before || !after)
goto usage;
table_init();
read_syms(before, after);
sym_cleanup();
return 0;
usage:
fprintf(stderr, "usage: %s profile [ profile ]\n", argv[0]);
return EXIT_FAILURE;
}
next prev parent reply other threads:[~2004-08-29 18:42 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-08-24 15:22 [util-linux] readprofile ignores the last element in /proc/profile mita akinobu
2004-08-29 16:22 ` William Lee Irwin III
2004-08-29 18:41 ` William Lee Irwin III [this message]
2004-08-29 19:26 ` Andries Brouwer
2004-08-29 21:23 ` William Lee Irwin III
2004-08-29 21:26 ` William Lee Irwin III
2004-08-29 23:25 ` Andries Brouwer
2004-08-30 0:26 ` William Lee Irwin III
2004-08-30 18:27 ` Paulo Marques
2004-08-30 20:48 ` William Lee Irwin III
2004-08-31 16:45 ` mita akinobu
2004-08-31 17:21 ` mita akinobu
2004-08-31 19:25 ` William Lee Irwin III
2004-08-31 19:45 ` William Lee Irwin III
2004-09-01 16:09 ` mita akinobu
2004-09-01 16:27 ` William Lee Irwin III
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040829184114.GS5492@holomorphy.com \
--to=wli@holomorphy.com \
--cc=aeb@cwi.nl \
--cc=amgta@yacht.ocn.ne.jp \
--cc=linux-kernel@vger.kernel.org \
--cc=rubini@ipvvis.unipv.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.