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:
parent
0b5aae7128
commit
fc42d83efc
12 changed files with 2193 additions and 1 deletions
82
pobj/pobj.h
Normal file
82
pobj/pobj.h
Normal 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 */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
SUBDIRS = pbl lladd libdfa 2pc timing apps
|
SUBDIRS = pbl lladd libdfa 2pc timing pobj apps
|
||||||
|
|
4
src/pobj/Makefile.am
Normal file
4
src/pobj/Makefile.am
Normal 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
8
src/pobj/common.h
Normal 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
20
src/pobj/debug.h
Normal 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
108
src/pobj/hash.c
Normal 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
18
src/pobj/hash.h
Normal 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
1545
src/pobj/pobj.c
Normal file
File diff suppressed because it is too large
Load diff
184
src/pobj/xmem.c
Normal file
184
src/pobj/xmem.c
Normal 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
34
src/pobj/xmem.h
Normal 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
84
test/pobj/test-list.c
Normal 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
105
test/pobj/test-multilist.c
Normal 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();
|
||||||
|
}
|
Loading…
Reference in a new issue