Skip to content

Commit 919a163

Browse files
mca/threads/qthreads: implement missing functionalities
Signed-off-by: Shintaro Iwasaki <siwasaki@anl.gov>
1 parent db3e598 commit 919a163

11 files changed

+339
-75
lines changed

opal/mca/threads/qthreads/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ sources = \
2727
threads_qthreads_condition.c \
2828
threads_qthreads_module.c \
2929
threads_qthreads_mutex.c \
30+
threads_qthreads_wait_sync.c \
3031
threads_qthreads_mutex.h \
3132
threads_qthreads_threads.h \
3233
threads_qthreads_tsd.h \

opal/mca/threads/qthreads/configure.m4

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,6 @@
2525

2626
AC_DEFUN([OPAL_CONFIG_QTHREADS],[
2727

28-
AC_CHECK_HEADERS([qthread/qthread.h],
29-
[AC_CHECK_LIB([qthread],[qthread_initialize],
30-
[threads_qthreads_happy="yes"],
31-
[threads_qthreads_happy="no"])],
32-
[threads_qthreads_happy="no"])
33-
3428
AC_ARG_WITH([qthreads],
3529
[AC_HELP_STRING([--with-qthreads=DIR],
3630
[Specify location of qthreads installation. Error if qthreads support cannot be found.])])
@@ -60,7 +54,7 @@ AC_DEFUN([OPAL_CONFIG_QTHREADS],[
6054

6155
AS_IF([test $opal_qthreads_happy = yes],
6256
[OPAL_CHECK_PACKAGE([opal_qthreads],
63-
[qthread/qthread.h],
57+
[qthread.h],
6458
[qthread],
6559
[qthread_initialize],
6660
[],

opal/mca/threads/qthreads/threads_qthreads.h.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@
2626
#ifndef OPAL_MCA_THREADS_QTHREADS_THREADS_QTHREADS_H
2727
#define OPAL_MCA_THREADS_QTHREADS_THREADS_QTHREADS_H 1
2828

29-
#include "@OPAL_QTHREADS_INCLUDE_PATH@qthread/qthread.h"
29+
#include "@OPAL_QTHREADS_INCLUDE_PATH@qthread.h"
30+
#include "@OPAL_QTHREADS_INCLUDE_PATH@qthread/tls.h"
3031

31-
static inline void ensure_init_qthreads(void)
32+
static inline void opal_threads_ensure_init_qthreads(void)
3233
{
3334
qthread_initialize();
3435
}

opal/mca/threads/qthreads/threads_qthreads_component.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "opal_config.h"
2525

26+
#include "opal/mca/threads/qthreads/threads_qthreads.h"
2627
#include "opal/mca/threads/thread.h"
2728
#include "opal/mca/threads/threads.h"
2829
#include "opal/constants.h"

opal/mca/threads/qthreads/threads_qthreads_module.c

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,8 @@
1919
* $HEADER$
2020
*/
2121

22-
#include <unistd.h>
23-
2422
#include "opal/mca/threads/qthreads/threads_qthreads.h"
2523
#include "opal/constants.h"
26-
#include "opal/util/sys_limits.h"
27-
#include "opal/util/output.h"
28-
#include "opal/prefetch.h"
2924
#include "opal/mca/threads/threads.h"
3025
#include "opal/mca/threads/tsd.h"
3126

@@ -34,40 +29,82 @@ struct opal_tsd_key_value {
3429
opal_tsd_destructor_t destructor;
3530
};
3631

37-
static int opal_main_thread;
38-
struct opal_tsd_key_value *opal_tsd_key_values = NULL;
39-
static int opal_tsd_key_values_count = 0;
32+
/* false: uninitialized, true: initialized. */
33+
static opal_atomic_lock_t opal_thread_self_key_lock = OPAL_ATOMIC_LOCK_INIT;
34+
static bool opal_thread_self_key_init = false;
35+
static opal_tsd_key_t opal_thread_self_key;
36+
37+
static inline void self_key_ensure_init(void)
38+
{
39+
if (false == opal_thread_self_key_init) {
40+
/* not initialized yet. */
41+
opal_atomic_lock(&opal_thread_self_key_lock);
42+
/* check again. */
43+
if (false == opal_thread_self_key_init) {
44+
/* This thread is responsible for initializing this key. */
45+
qthread_key_create(&opal_thread_self_key, NULL);
46+
opal_atomic_mb();
47+
opal_thread_self_key_init = true;
48+
}
49+
opal_atomic_unlock(&opal_thread_self_key_lock);
50+
}
51+
/* opal_thread_self_key has been already initialized. */
52+
}
4053

4154
/*
4255
* Constructor
4356
*/
4457
static void opal_thread_construct(opal_thread_t *t)
4558
{
59+
t->t_run = 0;
60+
t->t_thread_ret = 0;
4661
}
4762

4863
OBJ_CLASS_INSTANCE(opal_thread_t,
4964
opal_object_t,
5065
opal_thread_construct, NULL);
5166

67+
static inline aligned_t *opal_thread_get_qthreads_self(void)
68+
{
69+
self_key_ensure_init();
70+
void *ptr = qthread_getspecific(opal_thread_self_key);
71+
return (aligned_t *)ptr;
72+
}
5273

53-
opal_thread_t *opal_thread_get_self(void)
74+
static aligned_t opal_thread_qthreads_wrapper(void *arg)
5475
{
55-
return NULL;
76+
opal_thread_t *t = (opal_thread_t *)arg;
77+
78+
/* Register itself. */
79+
self_key_ensure_init();
80+
qthread_setspecific(opal_thread_self_key, t->t_thread_ret_ptr);
81+
82+
t->t_ret = ((void *(*)(void *))t->t_run)(t);
83+
return 0;
5684
}
5785

58-
bool opal_thread_self_compare(opal_thread_t *t)
86+
opal_thread_t *opal_thread_get_self(void)
5987
{
60-
return OPAL_ERR_NOT_IMPLEMENTED;
88+
opal_threads_ensure_init_qthreads();
89+
opal_thread_t *t = OBJ_NEW(opal_thread_t);
90+
t->t_thread_ret_ptr = opal_thread_get_qthreads_self();
91+
return t;
6192
}
6293

63-
int sync_wait_mt(void *p)
94+
bool opal_thread_self_compare(opal_thread_t *t)
6495
{
65-
return OPAL_ERR_NOT_IMPLEMENTED;
96+
opal_threads_ensure_init_qthreads();
97+
return opal_thread_get_qthreads_self() == &t->t_thread_ret;
6698
}
6799

68100
int opal_thread_join(opal_thread_t *t, void **thr_return)
69101
{
70-
return OPAL_ERR_NOT_IMPLEMENTED;
102+
qthread_readFF(NULL, t->t_thread_ret_ptr);
103+
if (thr_return) {
104+
*thr_return = t->t_ret;
105+
}
106+
t->t_thread_ret = 0;
107+
return OPAL_SUCCESS;
71108
}
72109

73110
void opal_thread_set_main(void)
@@ -76,12 +113,17 @@ void opal_thread_set_main(void)
76113

77114
int opal_thread_start(opal_thread_t *t)
78115
{
79-
return OPAL_ERR_NOT_IMPLEMENTED;
116+
opal_threads_ensure_init_qthreads();
117+
t->t_thread_ret_ptr = &t->t_thread_ret;
118+
qthread_fork(opal_thread_qthreads_wrapper, t, &t->t_thread_ret);
119+
return OPAL_SUCCESS;
80120
}
81121

82122
OBJ_CLASS_DECLARATION(opal_thread_t);
83123

84124
int opal_tsd_key_create(opal_tsd_key_t *key, opal_tsd_destructor_t destructor)
85125
{
86-
return OPAL_ERR_NOT_IMPLEMENTED;
126+
opal_threads_ensure_init_qthreads();
127+
qthread_key_create(key, destructor);
128+
return OPAL_SUCCESS;
87129
}

opal/mca/threads/qthreads/threads_qthreads_mutex.c

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ bool opal_uses_threads = false;
3636

3737
static void opal_mutex_construct(opal_mutex_t *m)
3838
{
39+
opal_threads_ensure_init_qthreads();
40+
opal_mutex_create(m);
3941
}
4042

4143
static void opal_mutex_destruct(opal_mutex_t *m)
@@ -56,36 +58,82 @@ OBJ_CLASS_INSTANCE(opal_recursive_mutex_t,
5658
opal_recursive_mutex_construct,
5759
opal_mutex_destruct);
5860

59-
static void opal_cond_create(opal_cond_t *cond)
60-
{
61-
ensure_init_qthreads();
62-
}
63-
6461
int opal_cond_init(opal_cond_t *cond)
6562
{
66-
return OPAL_ERR_NOT_IMPLEMENTED;
63+
opal_atomic_lock_init(&cond->m_lock, 0);
64+
cond->m_waiter_head = NULL;
65+
cond->m_waiter_tail = NULL;
66+
return OPAL_SUCCESS;
6767
}
6868

69+
typedef struct {
70+
int m_signaled;
71+
void *m_prev;
72+
} cond_waiter_t;
73+
6974
int opal_cond_wait(opal_cond_t *cond, opal_mutex_t *lock)
7075
{
71-
ensure_init_qthreads();
72-
return 0 == qthread_readFE(*cond, &lock->m_lock_qthreads) ? OPAL_SUCCESS
73-
: OPAL_ERROR;
76+
opal_threads_ensure_init_qthreads();
77+
/* This thread is taking "lock", so only this thread can access this
78+
* condition variable. */
79+
opal_atomic_lock(&cond->m_lock);
80+
cond_waiter_t waiter = { 0, NULL };
81+
if (NULL == cond->m_waiter_head) {
82+
cond->m_waiter_tail = (void *)&waiter;
83+
} else {
84+
((cond_waiter_t *)cond->m_waiter_head)->m_prev = (void *)&waiter;
85+
}
86+
cond->m_waiter_head = (void *)&waiter;
87+
opal_atomic_unlock(&cond->m_lock);
88+
89+
while (1) {
90+
opal_mutex_unlock(lock);
91+
qthread_yield();
92+
opal_mutex_lock(lock);
93+
/* Check if someone woke me up. */
94+
opal_atomic_lock(&cond->m_lock);
95+
int signaled = waiter.m_signaled;
96+
opal_atomic_unlock(&cond->m_lock);
97+
if (1 == signaled) {
98+
break;
99+
}
100+
/* Unlock the lock again. */
101+
}
102+
return OPAL_SUCCESS;
74103
}
75104

76105
int opal_cond_broadcast(opal_cond_t *cond)
77106
{
78-
ensure_init_qthreads();
79-
return 0 == qthread_fill(*cond) ? OPAL_SUCCESS : OPAL_ERROR;
107+
opal_atomic_lock(&cond->m_lock);
108+
while (NULL != cond->m_waiter_tail) {
109+
cond_waiter_t *p_cur_tail = (cond_waiter_t *)cond->m_waiter_tail;
110+
cond->m_waiter_tail = p_cur_tail->m_prev;
111+
/* Awaken one of threads in a FIFO manner. */
112+
p_cur_tail->m_signaled = 1;
113+
}
114+
/* No waiters. */
115+
cond->m_waiter_head = NULL;
116+
opal_atomic_unlock(&cond->m_lock);
117+
return OPAL_SUCCESS;
80118
}
81119

82120
int opal_cond_signal(opal_cond_t *cond)
83121
{
84-
ensure_init_qthreads();
85-
return 0 == qthread_fill(*cond) ? OPAL_SUCCESS : OPAL_ERROR;
122+
opal_atomic_lock(&cond->m_lock);
123+
if (NULL != cond->m_waiter_tail) {
124+
cond_waiter_t *p_cur_tail = (cond_waiter_t *)cond->m_waiter_tail;
125+
cond->m_waiter_tail = p_cur_tail->m_prev;
126+
/* Awaken one of threads. */
127+
p_cur_tail->m_signaled = 1;
128+
if (NULL == cond->m_waiter_tail) {
129+
cond->m_waiter_head = NULL;
130+
}
131+
}
132+
opal_atomic_unlock(&cond->m_lock);
133+
return OPAL_SUCCESS;
86134
}
87135

88136
int opal_cond_destroy(opal_cond_t *cond)
89137
{
90-
return OPAL_ERR_NOT_IMPLEMENTED;
138+
return OPAL_SUCCESS;
91139
}

0 commit comments

Comments
 (0)