This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "".
The branch, master has been updated
via 559d29d59f4db9e023cce4a7142e0f07561be41a (commit)
via 3258cd55d0d4c3fbe3bc4b381fde53152c19910b (commit)
via 7aac788b9da29e5efb63c73e94f9e4515c0b351b (commit)
from 7b036cac171f6cfe9a31cca02f79e35a1e1f4dcf (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 559d29d59f4db9e023cce4a7142e0f07561be41a
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Tue Apr 15 15:06:16 2014 -0400
add 2nd aesop condition variable test
commit 3258cd55d0d4c3fbe3bc4b381fde53152c19910b
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Tue Apr 15 15:02:23 2014 -0400
aesop condition variable test program
commit 7aac788b9da29e5efb63c73e94f9e4515c0b351b
Author: Phil Carns <carns(a)mcs.anl.gov>
Date: Tue Apr 15 14:49:35 2014 -0400
add condition variable resource
- renamed and slightly updated version of old sched resource from Triton
-----------------------------------------------------------------------
Summary of changes:
resources/sem/cond.c | 280 ++++++++++++++++++++++++++++
resources/sem/cond.hae | 72 +++++++
resources/sem/module.mk.in | 6 +-
resources/sem/test/cond-cancel.ae | 68 +++++++
resources/sem/test/cond-pthread-compare.ae | 140 ++++++++++++++
resources/sem/test/module.mk.in | 4 +-
6 files changed, 566 insertions(+), 4 deletions(-)
create mode 100644 resources/sem/cond.c
create mode 100644 resources/sem/cond.hae
create mode 100644 resources/sem/test/cond-cancel.ae
create mode 100644 resources/sem/test/cond-pthread-compare.ae
Diff of changes:
diff --git a/resources/sem/cond.c b/resources/sem/cond.c
new file mode 100644
index 0000000..af83b73
--- /dev/null
+++ b/resources/sem/cond.c
@@ -0,0 +1,280 @@
+/*
+ * (C) 2009 The University of Chicago
+ *
+ * See COPYRIGHT in top-level directory.
+ */
+
+/* This is an implementation of a condition variable API for Aesop.
+ *
+ * TODO: this implementation duplicates much of the logic of the sem
+ * resource. The two need to be merged or one built atop the other. See
+ * trac #???
+ */
+
+#include <errno.h>
+#include <aesop/aesop.h>
+#include <aesop/resource.h>
+#include "resources/sem/cond.h"
+
+struct aesop_cond_s
+{
+ ae_ops_t opqueue;
+};
+
+static triton_mutex_t cond_done_mutex;
+static ae_ops_t cond_done_queue;
+static int aesop_cond_resource_id;
+static triton_mutex_t module_lock = TRITON_MUTEX_INITIALIZER;
+static int module_refcount = 0;
+
+int aesop_cond_init(aesop_cond_t *cond)
+{
+ struct aesop_cond_s *s;
+ s = malloc(sizeof(*s));
+ if(s == NULL)
+ {
+ return AE_ERR_NOMEM;
+ }
+ ae_ops_init(&s->opqueue);
+ *cond = s;
+ return AE_SUCCESS;
+}
+
+void aesop_cond_destroy(aesop_cond_t cond)
+{
+ assert(ae_ops_empty(&cond->opqueue));
+ free(cond);
+}
+
+ae_define_post(int, aesop_cond_obj_wait, aesop_cond_t cond, triton_mutex_t *mutex, aesop_cond_id_t *result)
+{
+
+ if(ae_resource_is_cancelled())
+ {
+ *__ae_retval = AE_ERR_CANCELLED;
+ return AE_IMMEDIATE_COMPLETION;
+ }
+
+ if(result == NULL)
+ {
+ result = malloc(sizeof(*result));
+ if(!result)
+ {
+ return(AE_ERR_NOMEM);
+ }
+ result->internal = 1;
+ }
+ else
+ {
+ result->internal = 0;
+ }
+
+ assert(triton_mutex_trylock(mutex) == EBUSY);
+
+ ae_op_clear(&result->op);
+ ae_op_fill(&result->op);
+ result->mutex = mutex;
+ result->op_id = ae_id_gen(aesop_cond_resource_id, (uint64_t)result);
+ result->state = AESOP_COND_STATE_CONDULED;
+
+ ae_ops_enqueue(&result->op, &cond->opqueue);
+ triton_mutex_unlock(result->mutex);
+
+ *__ae_op_id = result->op_id;
+ return AE_SUCCESS;
+}
+
+void aesop_cond_notify_all(aesop_cond_t cond)
+{
+ struct ae_op *op;
+ aesop_cond_id_t *result;
+ int found_ops = 0;
+
+ while(!ae_ops_empty(&cond->opqueue))
+ {
+ found_ops = 1;
+
+ /* remove op from conduling queue */
+ op = ae_ops_dequeue(&cond->opqueue);
+ result = ae_op_entry(op, struct aesop_cond_id_s, op);
+ result->state = AESOP_COND_STATE_DONE;
+
+ /* add op to done queue */
+ triton_mutex_lock(&cond_done_mutex);
+ ae_ops_enqueue(op, &cond_done_queue);
+ triton_mutex_unlock(&cond_done_mutex);
+ }
+
+ if(found_ops)
+ {
+ ae_resource_request_poll(aesop_cond_resource_id);
+ }
+
+ return;
+}
+
+void aesop_cond_notify_next(aesop_cond_t cond)
+{
+ struct ae_op *op;
+ aesop_cond_id_t *result;
+ if(!ae_ops_empty(&cond->opqueue))
+ {
+ op = ae_ops_dequeue(&cond->opqueue);
+ result = ae_op_entry(op, struct aesop_cond_id_s, op);
+ result->state = AESOP_COND_STATE_DONE;
+
+ /* add op to done queue */
+ triton_mutex_lock(&cond_done_mutex);
+ ae_ops_enqueue(op, &cond_done_queue);
+ ae_resource_request_poll(aesop_cond_resource_id);
+ triton_mutex_unlock(&cond_done_mutex);
+ }
+ return;
+}
+
+void aesop_cond_notify_specific(aesop_cond_t cond, aesop_cond_id_t *id)
+{
+ ae_ops_del(&id->op);
+ id->state = AESOP_COND_STATE_DONE;
+
+ triton_mutex_lock(&cond_done_mutex);
+ ae_ops_enqueue(&id->op, &cond_done_queue);
+ ae_resource_request_poll(aesop_cond_resource_id);
+ triton_mutex_unlock(&cond_done_mutex);
+
+ return;
+}
+
+static int aesop_cond_cancel(ae_op_id_t op_id)
+{
+ int resource_id;
+ aesop_cond_id_t *rid;
+ intptr_t tmp_ptr;
+ int ret;
+
+ tmp_ptr = ae_id_lookup(op_id, &resource_id);
+ rid = (aesop_cond_id_t *)tmp_ptr;
+
+ assert(resource_id == aesop_cond_resource_id);
+
+ triton_mutex_lock(rid->mutex);
+ if(rid->state == AESOP_COND_STATE_CONDULED)
+ {
+ ae_ops_del(&rid->op);
+ rid->state = AESOP_COND_STATE_CANCELED;
+ triton_mutex_lock(&cond_done_mutex);
+ ae_ops_enqueue(&rid->op, &cond_done_queue);
+ ae_resource_request_poll(aesop_cond_resource_id);
+ triton_mutex_unlock(&cond_done_mutex);
+ ret = AE_SUCCESS;
+ }
+ else
+ {
+ ret = AE_ERR_OTHER;
+ }
+ triton_mutex_unlock(rid->mutex);
+ return ret;
+}
+
+static int aesop_cond_poll(void *arg)
+{
+ struct ae_op *op;
+ struct aesop_cond_id_s *result;
+ int internal;
+ int normal_completion;
+
+ triton_mutex_lock(&cond_done_mutex);
+ while(ae_ops_count(&cond_done_queue) > 0)
+ {
+ int ret;
+ void (*callback)(void *, int);
+ void *user_ptr;
+
+ op = ae_ops_dequeue(&cond_done_queue);
+ triton_mutex_unlock(&cond_done_mutex);
+ result = ae_op_entry(op, struct aesop_cond_id_s, op);
+ triton_mutex_lock(result->mutex);
+
+ internal = result->internal;
+ ret = result->state == AESOP_COND_STATE_CANCELED ? AE_ERR_CANCELLED : AE_SUCCESS;
+
+ normal_completion = ae_op_complete(op);
+ /* TODO: see aethread.c comments; it isn't clear how to get
+ * ae_op_complete to return 0.
+ */
+ assert(normal_completion);
+ if(internal)
+ {
+ ae_op_execute(op, int, ret);
+ free(result);
+ }
+ else
+ {
+ callback = op->callback;
+ user_ptr = op->user_ptr;
+ /* NOTE: the callback in this case might free the control
+ * structure that holds the op, so we can't touch it any more
+ * after calling the callback.
+ */
+ ae_op_clear(op);
+ callback(user_ptr, ret);
+ }
+
+ triton_mutex_lock(&cond_done_mutex);
+ }
+ triton_mutex_unlock(&cond_done_mutex);
+
+ return AE_SUCCESS;
+}
+
+static struct ae_resource aesop_cond_resource =
+{
+ .resource_name = "cond",
+ .poll = aesop_cond_poll,
+ .cancel = aesop_cond_cancel
+};
+
+int aesop_cond_resource_init(void)
+{
+ int ret;
+
+ triton_mutex_lock(&module_lock);
+
+ if(!module_refcount)
+ {
+ ae_ops_init(&cond_done_queue);
+ triton_mutex_init(&cond_done_mutex, NULL);
+
+ ret = ae_resource_register(&aesop_cond_resource, &aesop_cond_resource_id);
+ if(ret!= AE_SUCCESS)
+ {
+ triton_mutex_unlock(&module_lock);
+ return(AE_ERR_UNKNOWN);
+ }
+ }
+ module_refcount++;
+ triton_mutex_unlock(&module_lock);
+
+ return(AE_SUCCESS);
+}
+
+void aesop_cond_resource_finalize(void)
+{
+ triton_mutex_lock(&module_lock);
+ module_refcount--;
+
+ if(!module_refcount)
+ {
+ ae_resource_unregister(aesop_cond_resource_id);
+ }
+ triton_mutex_unlock(&module_lock);
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff --git a/resources/sem/cond.hae b/resources/sem/cond.hae
new file mode 100644
index 0000000..7a20599
--- /dev/null
+++ b/resources/sem/cond.hae
@@ -0,0 +1,72 @@
+/*
+ * (C) 2009 The University of Chicago
+ *
+ * See COPYRIGHT in top-level directory.
+ */
+
+#ifndef __COND_HAE__
+#define __COND_HAE__
+
+#include <pthread.h>
+#include <aesop/aesop.h>
+#include <aesop/op.h>
+#include <sys/time.h>
+
+enum aesop_cond_state
+{
+ AESOP_COND_STATE_CONDULED,
+ AESOP_COND_STATE_DONE,
+ AESOP_COND_STATE_CANCELED
+};
+
+/* TODO: this should probably be a forward definition */
+typedef struct aesop_cond_id_s
+{
+ pthread_mutex_t *mutex;
+ enum aesop_cond_state state;
+ ae_op_id_t op_id;
+ struct ae_op op;
+ int internal;
+} aesop_cond_id_t;
+
+typedef struct aesop_cond_s *aesop_cond_t;
+
+int aesop_cond_resource_init(void);
+void aesop_cond_resource_finalize(void);
+
+int aesop_cond_init(aesop_cond_t *cond);
+void aesop_cond_destroy(aesop_cond_t cond);
+
+void aesop_cond_notify_all(aesop_cond_t cond);
+void aesop_cond_notify_next(aesop_cond_t cond);
+void aesop_cond_notify_specific(aesop_cond_t cond, aesop_cond_id_t *id);
+
+/* gets the envelope structure pointer from the conduling id:
+ *
+ * aesop_cond_get_envelope(aesop_cond_id_t id, envelope_type, cond_id_member_name);
+ */
+#define aesop_cond_get_envelope(_id, _type, _member) \
+ ((_type *)((char *)(_id) - (unsigned long)((&((_type *)0)->_member))))
+
+/**
+ * aesop_cond_obj_wait waits on a conduling object to be notified. The mutex passed in
+ * must be locked.
+ */
+__blocking int aesop_cond_obj_wait(aesop_cond_t cond, pthread_mutex_t *mutex, aesop_cond_id_t *result);
+
+/**
+ * Just wait on a conduling variable without a conduling id. No way to wake up individuals, only notify_all or
+ * notify_next can be used.
+ */
+#define aesop_cond_wait(_cond, _mutex) aesop_cond_obj_wait(_cond, _mutex, NULL)
+
+#endif
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff --git a/resources/sem/module.mk.in b/resources/sem/module.mk.in
index 78602f9..045a524 100644
--- a/resources/sem/module.mk.in
+++ b/resources/sem/module.mk.in
@@ -1,9 +1,9 @@
DIR := resources/sem
-AESOP_HDR += $(DIR)/sem.hae
+AESOP_HDR += $(DIR)/sem.hae $(DIR)/cond.hae
-INSTALL_HDR += $(DIR)/sem.hae
+INSTALL_HDR += $(DIR)/sem.hae $(DIR)/cond.hae
-LIBSRC += $(DIR)/sem.c
+LIBSRC += $(DIR)/sem.c $(DIR)/cond.c
diff --git a/resources/sem/test/cond-cancel.ae b/resources/sem/test/cond-cancel.ae
new file mode 100644
index 0000000..dced7db
--- /dev/null
+++ b/resources/sem/test/cond-cancel.ae
@@ -0,0 +1,68 @@
+
+#include "resources/sem/cond.hae"
+#include <aesop/timer.hae>
+
+struct limit_obj
+{
+ int ind;
+};
+
+static aesop_cond_t foo_cond;
+static triton_mutex_t foo_mutex = TRITON_MUTEX_INITIALIZER;
+
+__blocking int dolimit(struct limit_obj *obj);
+
+static __blocking int dostuff(void)
+{
+
+ pwait
+ {
+ pbranch
+ {
+ int ret;
+
+ triton_mutex_lock(&foo_mutex);
+ ret = aesop_cond_wait(foo_cond, &foo_mutex);
+ triton_mutex_unlock(&foo_mutex);
+
+ assert(ret == AE_ERR_CANCELLED);
+ printf("SUCCESS: aesop_cond_wait() returned AE_ERR_CANCELED.\n");
+ }
+ pbranch
+ {
+ aesop_timer(1000);
+ printf("about to cancel...\n");
+ aesop_cancel_branches();
+ }
+ }
+
+ return 0;
+}
+
+__blocking int aesop_main(int argc, char **argv)
+{
+ int ret;
+
+ aesop_cond_resource_init();
+ aesop_timer_init();
+
+ aesop_cond_init(&foo_cond);
+
+ ret = dostuff();
+ assert(ret == 0);
+
+ aesop_timer_finalize();
+ aesop_cond_resource_finalize();
+
+ return ret;
+}
+aesop_main_set(aesop_main);
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff --git a/resources/sem/test/cond-pthread-compare.ae b/resources/sem/test/cond-pthread-compare.ae
new file mode 100644
index 0000000..249b497
--- /dev/null
+++ b/resources/sem/test/cond-pthread-compare.ae
@@ -0,0 +1,140 @@
+
+#include <pthread.h>
+#include <aesop/aesop.h>
+#include "resources/sem/cond.hae"
+
+static pthread_cond_t cond;
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static aesop_cond_t acond;
+static triton_mutex_t cond_mutex = TRITON_MUTEX_INITIALIZER;
+
+#define ITERATIONS 200
+int flag = 0;
+
+static __blocking int cond_test(void)
+{
+ struct timeval t1, t2, diff;
+
+ gettimeofday(&t1, NULL);
+ pwait
+ {
+ int i;
+ for(i = 0; i < ITERATIONS; ++i)
+ {
+ pbranch
+ {
+ triton_mutex_lock(&cond_mutex);
+ while(!flag)
+ aesop_cond_wait(acond, &cond_mutex);
+ triton_mutex_unlock(&cond_mutex);
+ }
+ }
+ }
+ gettimeofday(&t2, NULL);
+ diff.tv_sec = t2.tv_sec - t1.tv_sec;
+ diff.tv_usec = t2.tv_usec - t1.tv_usec;
+ if(t2.tv_usec < t1.tv_usec)
+ {
+ diff.tv_sec--;
+ diff.tv_usec += 1e6;
+ }
+ printf("Aesop cond time: %d.%06d secs\n", (int)diff.tv_sec, (int)diff.tv_usec);
+ return 0;
+}
+
+static void *thread_cb(void *up)
+{
+ pthread_mutex_lock(&mutex);
+ while(!flag)
+ pthread_cond_wait(&cond, &mutex);
+ pthread_mutex_unlock(&mutex);
+
+ return NULL;
+}
+
+static void thread_test(void)
+{
+ int i, ret;
+ pthread_t tid[ITERATIONS];
+ void *val;
+ struct timeval t1, t2, diff;
+
+ gettimeofday(&t1, NULL);
+ for(i = 0; i < ITERATIONS; ++i)
+ {
+ ret = pthread_create(&tid[i], NULL, thread_cb, NULL);
+ if(ret != 0)
+ {
+ perror("pthread_create failed!\n");
+ assert(ret == 0);
+ }
+ }
+
+ pthread_mutex_lock(&mutex);
+ flag = 1;
+ pthread_cond_broadcast(&cond);
+ pthread_mutex_unlock(&mutex);
+
+ for(i = 0; i < ITERATIONS; ++i)
+ {
+ pthread_join(tid[i], &val);
+ }
+ gettimeofday(&t2, NULL);
+ diff.tv_sec = t2.tv_sec - t1.tv_sec;
+ diff.tv_usec = t2.tv_usec - t1.tv_usec;
+ if(t2.tv_usec < t1.tv_usec)
+ {
+ diff.tv_sec--;
+ diff.tv_usec += 1e6;
+ }
+ printf("thread time: %d.%06d secs\n", (int)diff.tv_sec, (int)diff.tv_usec);
+}
+
+__blocking int aesop_main(int argc, char **argv)
+{
+ int ret;
+
+ aesop_cond_resource_init();
+
+ aesop_cond_init(&acond);
+
+ pwait
+ {
+ pbranch
+ {
+ ret = cond_test();
+ assert(ret == 0);
+ }
+ pbranch
+ {
+ triton_mutex_lock(&cond_mutex);
+ flag = 1;
+ aesop_cond_notify_all(acond);
+ triton_mutex_unlock(&cond_mutex);
+ }
+ }
+
+ flag = 0;
+
+ aesop_cond_destroy(acond);
+
+ aesop_cond_resource_finalize();
+
+ pthread_cond_init(&cond, NULL);
+ thread_test();
+
+ flag = 0;
+
+ return 0;
+}
+aesop_main_set(aesop_main);
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: ts=8 sts=4 sw=4 expandtab
+ */
diff --git a/resources/sem/test/module.mk.in b/resources/sem/test/module.mk.in
index 1b31fad..987b620 100644
--- a/resources/sem/test/module.mk.in
+++ b/resources/sem/test/module.mk.in
@@ -3,5 +3,7 @@ DIR := resources/sem/test
AETESTSRC += $(DIR)/simple-sem.ae \
$(DIR)/cancel-sem.ae \
$(DIR)/cancel-sem-forloop.ae \
- $(DIR)/cancel-sem-before-down.ae
+ $(DIR)/cancel-sem-before-down.ae \
+ $(DIR)/cond-pthread-compare.ae \
+ $(DIR)/cond-cancel.ae
hooks/post-receive
--