Added pobj library sources, header file, and test programs. Small changes were

made to src/Makefile.am in order to include src/pobj build, but no corresponding
change was made to test/Makefile.am (will be done in the near future).
This commit is contained in:
Gilad Arnold 2004-12-13 21:51:11 +00:00
parent 0b5aae7128
commit fc42d83efc
12 changed files with 2193 additions and 1 deletions

82
pobj/pobj.h Normal file
View file

@ -0,0 +1,82 @@
#ifndef __POBJ_H
#define __POBJ_H
#define member_sizeof(s,x) (sizeof(((s *)NULL)->x))
#define member_offset(s,x) ((int)&(((s *)NULL)->x))
struct pobj_memfunc {
void *(*malloc) (size_t);
void *(*calloc) (size_t, size_t);
void *(*realloc) (void *, size_t);
void (*free) (void *);
};
/* Transactional markers. */
int pobj_start (void);
int pobj_end (void);
/* Memory management calls. */
void *pobj_malloc (size_t);
void *pobj_malloc_transient (size_t);
void *pobj_calloc (size_t, size_t);
void *pobj_calloc_transient (size_t, size_t);
void pobj_free (void *);
/* GC-oriented memory management calls (experts only!). */
void *pobj_malloc_adhoc (size_t, void *(*) (size_t), void (*) (void *));
void *pobj_malloc_transient_adhoc (size_t, void *(*) (size_t), void (*) (void *));
void *pobj_calloc_adhoc (size_t, size_t, void *(*) (size_t), void (*) (void *));
void *pobj_calloc_transient_adhoc (size_t, size_t, void *(*) (size_t),
void (*) (void *));
void pobj_finalize (void *);
void pobj_finalize_raw (void *);
void pobj_free_raw (void *);
int pobj_ref_flag (void *, void *);
int pobj_ref_unflag (void *, void *);
#define POBJ_REF_FLAG(obj,fld) pobj_ref_flag((obj), &((obj)->fld))
#define POBJ_REF_UNFLAG(obj,fld) pobj_ref_unflag((obj), &((obj)->fld))
int pobj_ref_typify (void *, int *);
void *pobj_memcpy (void *, void *, void *, size_t);
int pobj_set_int (void *, int *, int);
int pobj_set_unsigned (void *, unsigned *, unsigned);
int pobj_set_long (void *, long *, long);
int pobj_set_unsigned_long (void *, unsigned long *, unsigned long);
int pobj_set_short (void *, short *, short);
int pobj_set_unsigned_short (void *, unsigned short *, unsigned short);
int pobj_set_char (void *, char *, char);
int pobj_set_unsigned_char (void *, unsigned char *, unsigned char);
int pobj_set_float (void *, float *, float);
int pobj_set_double (void *, double *, double);
int pobj_set_ref (void *, void *, void *);
#define POBJ_MEMCPY(obj,fld,data,len) pobj_memcpy((obj), &((obj)->fld), data, len)
#define POBJ_SET_INT(obj,fld,data) pobj_set_int((obj), &((obj)->fld), data)
#define POBJ_SET_UNSIGNED(obj,fld,data) \
pobj_set_unsigned((obj), &((obj)->fld), data)
#define POBJ_SET_LONG(obj,fld,data) pobj_set_long((obj), &((obj)->fld), data)
#define POBJ_SET_UNSIGNED_LONG(obj,fld,data) \
pobj_set_unsigned_long((obj), &((obj)->fld), data)
#define POBJ_SET_SHORT(obj,fld,data) pobj_set_short((obj), &((obj)->fld), data)
#define POBJ_SET_UNSIGNED_SHORT(obj,fld,data) \
pobj_set_unsigned_short((obj), &((obj)->fld), data)
#define POBJ_SET_CHAR(obj,fld,data) pobj_set_char((obj), &((obj)->fld), data)
#define POBJ_SET_UNSIGNED_CHAR(obj,fld,data) \
pobj_set_unsigned_char((obj), &((obj)->fld), data)
#define POBJ_SET_FLOAT(obj,fld,data) pobj_set_float((obj), &((obj)->fld), data)
#define POBJ_SET_DOUBLE(obj,fld,data) pobj_set_double((obj), &((obj)->fld), data)
#define POBJ_SET_REF(obj,fld,ref) pobj_set_ref((obj), &((obj)->fld), ref)
int pobj_update (void *);
int pobj_update_recursive (void *);
int pobj_static_set_ref (void *, void *);
int pobj_static_update_ref (void *);
int pobj_init (struct pobj_memfunc *);
int pobj_shutdown (void);
#endif /* __POBJ_H */

View file

@ -1 +1 @@
SUBDIRS = pbl lladd libdfa 2pc timing apps SUBDIRS = pbl lladd libdfa 2pc timing pobj apps

4
src/pobj/Makefile.am Normal file
View file

@ -0,0 +1,4 @@
lib_LIBRARIES=libpobj.a
libpobj_a_SOURCES=xmem.c hash.c pobj.c
librw_a_SOURCES=rw.c
AM_CFLAGS= -g -Wall -pedantic -std=gnu99

8
src/pobj/common.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef __COMMON_H
#define __COMMON_H
#define member_sizeof(s,x) (sizeof(((s *)NULL)->x))
#define member_offset(s,x) ((int)&(((s *)NULL)->x))
#endif /* __COMMON_H */

20
src/pobj/debug.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef __DEBUG_H
#define __DEBUG_H
#include <stdio.h>
/* FIXME: send that to the make system. */
#define HAVE_DEBUG
#ifdef HAVE_DEBUG
#define debug(format,...) \
fprintf (stderr, "[%.13s%*c:%4d] " format "\n", \
__FUNCTION__, (strlen(__FUNCTION__) > 13 ? 1 : 14 - strlen(__FUNCTION__)), \
' ', __LINE__, ##__VA_ARGS__), \
fflush (stderr)
#else
#define debug(format,...) ((void)0)
#endif /* HAVE_DEBUG */
#endif /* __DEBUG_H */

108
src/pobj/hash.c Normal file
View file

@ -0,0 +1,108 @@
#include <string.h>
#include "hash.h"
#include "debug.h"
#include "xmem.h"
/* Hash item. */
struct hash_item {
struct hash_item *next;
unsigned long key;
unsigned long val;
};
void
hash_init (hash_table table, int nbuckexp)
{
int bucket_max = (int) ((unsigned long) 1 << nbuckexp);
memset (table, 0, bucket_max * sizeof (struct hash_item *));
}
void
hash_close (hash_table table, int nbuckexp)
{
int bucket_max = (int) ((unsigned long) 1 << nbuckexp);
struct hash_item *bucket, *next;
int i;
for (i = 0; i < bucket_max; i++) {
for (bucket = table[i]; bucket; bucket = next) {
next = bucket->next;
XFREE (XMEM_HASH, bucket);
}
table[i] = NULL;
}
}
unsigned long
hash_lookup (hash_table table, int nbuckexp, unsigned long key)
{
int bucket_index = (int) (key & (((unsigned long) 1 << nbuckexp) - 1));
struct hash_item *bucket;
unsigned long val;
debug ("tracing bucket %d for key %lu (%p)",
bucket_index, key, (void *) key);
for (bucket = table[bucket_index]; bucket; bucket = bucket->next)
if (bucket->key == key) {
val = bucket->val;
debug ("found %lu->%lu (%p->%p)",
key, val, (void *) key, (void *) val);
return val;
}
debug ("not found");
return 0;
}
void
hash_insert (hash_table table, int nbuckexp,
unsigned long key, unsigned long val)
{
int bucket_index = (int) (key & (((unsigned long) 1 << nbuckexp) - 1));
struct hash_item *new;
debug ("inserting %lu->%lu (%p->%p) to bucket %d",
key, val, (void *) key, (void *) val, bucket_index);
new = (struct hash_item *) XMALLOC (XMEM_HASH, sizeof (struct hash_item));
new->key = key;
new->val = val;
new->next = table[bucket_index];
table[bucket_index] = new;
}
unsigned long
hash_delete (hash_table table, int nbuckexp, unsigned long key)
{
int bucket_index = (int) (key & (((unsigned long) 1 << nbuckexp) - 1));
struct hash_item *bucket, *prev;
unsigned long val;
debug ("tracing bucket %d for key %lu (%p)",
bucket_index, key, (void *) key);
for (prev = NULL, bucket = table[bucket_index]; bucket;
prev = bucket, bucket = bucket->next)
if (bucket->key == key) {
val = bucket->val;
debug ("deleting %lu->%lu (%p->%p)",
key, val, (void *) key, (void *) val);
if (prev)
prev->next = bucket->next;
else
table[bucket_index] = bucket->next;
XFREE (XMEM_HASH, bucket);
return val;
}
debug ("not found");
return 0;
}

18
src/pobj/hash.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef __HASH_H
#define __HASH_H
/* Hash table type and declaration macro. */
typedef struct hash_item **hash_table;
#define HASH_DECLARE(name,nbuckexp) struct hash_item *name[1 << nbuckexp]
/* Prototypes. */
void hash_init (hash_table, int);
void hash_close (hash_table, int);
unsigned long hash_lookup (hash_table, int, unsigned long);
void hash_insert (hash_table, int, unsigned long, unsigned long);
unsigned long hash_delete (hash_table, int, unsigned long);
#endif /* __HASH_H */

1545
src/pobj/pobj.c Normal file

File diff suppressed because it is too large Load diff

184
src/pobj/xmem.c Normal file
View file

@ -0,0 +1,184 @@
#include <stdlib.h>
#include "common.h"
#include "xmem.h"
struct xmem {
#ifdef HAVE_XMEM_DETAIL
/* Extended memory block info. */
int mtype;
char *file;
int line;
int size;
struct xmem *prev;
struct xmem *next;
#endif /* HAVE_XMEM_DETAIL */
/* Dummy field used to infer alignment. */
int dummy;
};
#define XMEM_OFFSET member_offset (struct xmem, dummy)
#ifdef HAVE_XMEM
struct xmem_stat {
unsigned long count;
#ifdef HAVE_XMEM_DETAIL
unsigned long size;
struct xmem *head;
struct xmem *tail;
#endif /* HAVE_XMEM_DETAIL */
} xmem_stats[XMEM_MAX] = { { 0 } };
#endif /* HAVE_XMEM */
void *
xmem_malloc (int mtype, char *file, int line, size_t size)
{
struct xmem *x;
x = (struct xmem *) malloc (size + XMEM_OFFSET);
if (! x)
exit (1);
#ifdef HAVE_XMEM_DETAIL
/* Update object's extended info. */
x->mtype = mtype;
x->file = file;
x->line = line;
x->size = size;
/* Attach to object type list. */
x->next = NULL;
x->prev = xmem_stats[mtype].tail;
if (xmem_stats[mtype].tail)
xmem_stats[mtype].tail->next = x;
xmem_stats[mtype].tail = x;
if (! xmem_stats[mtype].head)
xmem_stats[mtype].head = x;
/* Update accumulated object sizes. */
xmem_stats[mtype].size += (unsigned long) size;
#endif /* HAVE_XMEM_DETAIL */
#ifdef HAVE_XMEM
/* Update accumulated type counter. */
xmem_stats[mtype].count++;
#endif /* HAVE_XMEM */
return (void *) (((char *) x) + XMEM_OFFSET);
}
void
xmem_free (int mtype, void *p)
{
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET);
#ifdef HAVE_XMEM_DETAIL
/* Verify object type consistency. */
if (mtype == XMEM_MAX)
mtype = x->mtype;
else if (mtype != x->mtype)
exit (1);
/* Detach from type list. */
if (x->prev)
x->prev->next = x->next;
else
xmem_stats[mtype].head = x->next;
if (x->next)
x->next->prev = x->prev;
else
xmem_stats[mtype].tail = x->prev;
/* Update accumulated object sizes. */
xmem_stats[mtype].size -= (unsigned long) x->size;
#endif /* HAVE_XMEM_DETAIL */
#ifdef HAVE_XMEM
/* Update accumulated type counter. */
xmem_stats[mtype].count--;
#endif /* HAVE_XMEM */
free (x);
}
int
xmem_obj_mtype (void *p)
{
#ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET);
return x->mtype;
#else
return 0;
#endif /* HAVE_XMEM_DETAIL */
}
char *
xmem_obj_file (void *p)
{
#ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET);
return x->file;
#else
return NULL;
#endif /* HAVE_XMEM_DETAIL */
}
int
xmem_obj_line (void *p)
{
#ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET);
return x->line;
#else
return 0;
#endif /* HAVE_XMEM_DETAIL */
}
size_t
xmem_obj_size (void *p)
{
#ifdef HAVE_XMEM_DETAIL
struct xmem *x = (struct xmem *) (((char *) p) - XMEM_OFFSET);
return x->size;
#else
return 0;
#endif /* HAVE_XMEM_DETAIL */
}
unsigned long
xmem_stat_count (int mtype)
{
#ifdef HAVE_XMEM
return xmem_stats[mtype].count;
#else
return 0;
#endif /* HAVE_XMEM */
}
unsigned long
xmem_stat_size (int mtype)
{
#ifdef HAVE_XMEM_DETAIL
return xmem_stats[mtype].size;
#else
return 0;
#endif /* HAVE_XMEM_DETAIL */
}
unsigned long
xmem_stat_alloc_list (int mtype, void (*cb) (char *, int, size_t, void *))
{
unsigned long count = 0;
#ifdef HAVE_XMEM_DETAIL
struct xmem *x = xmem_stats[mtype].head;
while (x) {
cb (x->file, x->line, x->size, ((char *) x) + XMEM_OFFSET);
count++;
x = x->next;
}
#endif /* HAVE_XMEM_DETAIL */
return count;
}

34
src/pobj/xmem.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef __XMEM_H
#define __XMEM_H
enum {
/* General purpose identifiers. */
XMEM_TMP = 0,
XMEM_STR,
/* Dedicated object identifiers. */
XMEM_POBJ,
XMEM_HASH,
/* Teminator (don't use). */
XMEM_MAX
};
#define XMALLOC(t,s) xmem_malloc (t, __FILE__, __LINE__, s)
#define XFREE(t,p) xmem_free (t, p)
#ifdef HAVE_XMEM_DETAIL
#define XFREE_ANY(p) xmem_free (XMEM_MAX, p)
#endif /* HAVE_XMEM_DETAIL */
void *xmem_malloc (int, char *, int, size_t);
void xmem_free (int, void *);
int xmem_obj_mtype (void *);
char *xmem_obj_file (void *);
int xmem_obj_line (void *);
size_t xmem_obj_size (void *);
unsigned long xmem_stat_count (int);
unsigned long xmem_stat_size (int);
unsigned long xmem_stat_alloc_list (int, void (*cb) (char *, int, size_t, void *));
#endif /* __XMEM_H */

84
test/pobj/test-list.c Normal file
View file

@ -0,0 +1,84 @@
#include <stdio.h>
#include <stdlib.h>
#include "pobj.h"
#include "common.h"
struct item {
int val;
struct item *next;
int dummy[45];
};
int item_ref_fields[] = {
member_offset(struct item, next),
-1
};
int
main (int argc, char **argv)
{
static struct item *list = NULL;
struct item *tmp, *next;
int i;
switch (pobj_init (NULL)) {
case 0:
printf ("first-time init\n");
/* Build list. */
next = NULL;
for (i = 0; i < 10; i++) {
pobj_start ();
tmp = (struct item *) pobj_malloc (sizeof (struct item));
if (! tmp) {
printf ("allocation error\n");
abort ();
}
/* pobj_ref_typify (tmp, item_ref_fields); */
#if 0
tmp->val = i;
tmp->next = next;
#endif
pobj_static_set_ref (&list, tmp);
POBJ_SET_INT (tmp, val, i);
/* Intended crash code... */
#if 0
if (i == 7)
abort ();
#endif
POBJ_SET_REF (tmp, next, next);
pobj_end ();
/* pobj_update (tmp); */
next = tmp;
}
/* pobj_update_recursive (tmp); */
/* pobj_static_set_ref (&list, tmp); */
/* list = tmp; */
/* pobj_static_update_ref (&list); */
break;
case 1:
printf ("subsequent init\n");
break;
case -1:
printf ("init error\n");
break;
default:
printf ("unknown return value\n");
}
/* Print list. */
printf ("printing list...\n");
for (tmp = list; tmp; tmp = tmp->next)
printf ("%p: val=%d next=%p\n",
(void *) tmp, tmp->val, (void *) tmp->next);
printf ("...done\n");
pobj_shutdown ();
return 0;
}

105
test/pobj/test-multilist.c Normal file
View file

@ -0,0 +1,105 @@
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "pobj.h"
#include "common.h"
#define MAX_MSG_SIZE 128
struct node {
char *data;
struct node *next;
};
typedef struct node Node;
int node_ref_fields[] = {
member_offset(struct node, data),
member_offset(struct node, next),
-1
};
pthread_mutex_t *lock;
Node *head = NULL;
Node *tail = NULL;
void print() {
Node *tmp = head;
while (tmp != NULL) {
printf("%s\n", tmp->data);
tmp = tmp->next;
}
}
Node *createNode(int id, int num) {
Node *tmp;
//pobj_start();
tmp = (Node *) pobj_malloc(sizeof(Node));
pobj_ref_typify(tmp, node_ref_fields);
tmp->data = (char *) pobj_malloc(sizeof(char) * MAX_MSG_SIZE);
sprintf(tmp->data, "%d: This is message #%d", id, num);
tmp->next = NULL;
pobj_update(tmp);
pobj_update(tmp->data);
//pobj_end();
return tmp;
}
void *work(void *pid) {
int id = *((int *) pid);
int i;
for (i = 0; i <= id; i++) {
/* pthread_mutex_lock(lock); */
Node *tmp = createNode(id, i);
pthread_mutex_lock(lock);
//pobj_start();
if (head == NULL) {
/* head = tail = tmp; */
pobj_static_set_ref(&head, tmp);
pobj_static_set_ref(&tail, tmp);
} else {
tail->next = tmp;
/* tail = tmp; */
pobj_update(tail);
pobj_static_set_ref(&tail, tmp);
}
//pobj_end();
pthread_mutex_unlock(lock);
}
return NULL;
}
void message(char *msg) {
printf("MASTER: %s\n", msg);
}
int main(int argc, char **argv) {
int num = 5;
if (argc > 1) {
num = atoi(argv[1]);
}
if (pobj_init(NULL) == 0) {
pthread_t threads[num];
int ids[num];
int i;
message("First run");
lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(lock, NULL);
pthread_mutex_lock(lock);
for (i = 0; i < num; i++) {
ids[i] = i;
pthread_create(&threads[i], NULL, work, (void *) &ids[i]);
}
pthread_mutex_unlock(lock);
for (i = 0; i < num; i++) {
pthread_join(threads[i], NULL);
}
} else {
message("Subsequent run");
}
print();
pobj_shutdown();
}