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