1 /* 2 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana 3 * University Research and Technology 4 * Corporation. All rights reserved. 5 * Copyright (c) 2004-2006 The University of Tennessee and The University 6 * of Tennessee Research Foundation. All rights 7 * reserved. 8 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, 9 * University of Stuttgart. All rights reserved. 10 * Copyright (c) 2004-2005 The Regents of the University of California. 11 * All rights reserved. 12 * Copyright (c) 2010 Cisco Systems, Inc. All rights reserved. 13 * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. 14 * Copyright (c) 2015-2017 Research Organization for Information Science 15 * and Technology (RIST). All rights reserved. 16 * Copyright (c) 2017-2019 Intel, Inc. All rights reserved. 17 * $COPYRIGHT$ 18 * 19 * Additional copyrights may follow 20 * 21 * $HEADER$ 22 */ 23 24 #ifndef PMIX_THREAD_H 25 #define PMIX_THREAD_H 1 26 27 #include "pmix_config.h" 28 29 #include <pthread.h> 30 #include <signal.h> 31 32 #include "src/class/pmix_object.h" 33 #if PMIX_ENABLE_DEBUG 34 #include "src/util/output.h" 35 #endif 36 37 #include "mutex.h" 38 39 BEGIN_C_DECLS 40 41 typedef void *(*pmix_thread_fn_t) (pmix_object_t *); 42 43 #define PMIX_THREAD_CANCELLED ((void*)1); 44 45 struct pmix_thread_t { 46 pmix_object_t super; 47 pmix_thread_fn_t t_run; 48 void* t_arg; 49 pthread_t t_handle; 50 }; 51 52 typedef struct pmix_thread_t pmix_thread_t; 53 54 #if PMIX_ENABLE_DEBUG 55 PMIX_EXPORT extern bool pmix_debug_threads; 56 #endif 57 58 59 PMIX_EXPORT PMIX_CLASS_DECLARATION(pmix_thread_t); 60 61 #define pmix_condition_wait(a,b) pthread_cond_wait(a, &(b)->m_lock_pthread) 62 typedef pthread_cond_t pmix_condition_t; 63 #define pmix_condition_broadcast(a) pthread_cond_broadcast(a) 64 #define pmix_condition_signal(a) pthread_cond_signal(a) 65 #define PMIX_CONDITION_STATIC_INIT PTHREAD_COND_INITIALIZER 66 67 typedef struct { 68 pmix_status_t status; 69 pmix_mutex_t mutex; 70 pmix_condition_t cond; 71 volatile bool active; 72 } pmix_lock_t; 73 74 #define PMIX_CONSTRUCT_LOCK(l) \ 75 do { \ 76 PMIX_CONSTRUCT(&(l)->mutex, pmix_mutex_t); \ 77 pthread_cond_init(&(l)->cond, NULL); \ 78 /* coverity[missing_lock : FALSE] */ \ 79 (l)->active = true; \ 80 } while(0) 81 82 #define PMIX_DESTRUCT_LOCK(l) \ 83 do { \ 84 PMIX_DESTRUCT(&(l)->mutex); \ 85 pthread_cond_destroy(&(l)->cond); \ 86 } while(0) 87 88 89 #if PMIX_ENABLE_DEBUG 90 #define PMIX_ACQUIRE_THREAD(lck) \ 91 do { \ 92 pmix_mutex_lock(&(lck)->mutex); \ 93 if (pmix_debug_threads) { \ 94 pmix_output(0, "Waiting for thread %s:%d", \ 95 __FILE__, __LINE__); \ 96 } \ 97 while ((lck)->active) { \ 98 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \ 99 } \ 100 if (pmix_debug_threads) { \ 101 pmix_output(0, "Thread obtained %s:%d", \ 102 __FILE__, __LINE__); \ 103 } \ 104 PMIX_ACQUIRE_OBJECT(lck); \ 105 (lck)->active = true; \ 106 } while(0) 107 #else 108 #define PMIX_ACQUIRE_THREAD(lck) \ 109 do { \ 110 pmix_mutex_lock(&(lck)->mutex); \ 111 while ((lck)->active) { \ 112 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \ 113 } \ 114 PMIX_ACQUIRE_OBJECT(lck); \ 115 (lck)->active = true; \ 116 } while(0) 117 #endif 118 119 120 #if PMIX_ENABLE_DEBUG 121 #define PMIX_WAIT_THREAD(lck) \ 122 do { \ 123 pmix_mutex_lock(&(lck)->mutex); \ 124 if (pmix_debug_threads) { \ 125 pmix_output(0, "Waiting for thread %s:%d", \ 126 __FILE__, __LINE__); \ 127 } \ 128 while ((lck)->active) { \ 129 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \ 130 } \ 131 if (pmix_debug_threads) { \ 132 pmix_output(0, "Thread obtained %s:%d", \ 133 __FILE__, __LINE__); \ 134 } \ 135 PMIX_ACQUIRE_OBJECT(lck); \ 136 pmix_mutex_unlock(&(lck)->mutex); \ 137 } while(0) 138 #else 139 #define PMIX_WAIT_THREAD(lck) \ 140 do { \ 141 pmix_mutex_lock(&(lck)->mutex); \ 142 while ((lck)->active) { \ 143 pmix_condition_wait(&(lck)->cond, &(lck)->mutex); \ 144 } \ 145 PMIX_ACQUIRE_OBJECT(lck); \ 146 pmix_mutex_unlock(&(lck)->mutex); \ 147 } while(0) 148 #endif 149 150 151 #if PMIX_ENABLE_DEBUG 152 #define PMIX_RELEASE_THREAD(lck) \ 153 do { \ 154 if (pmix_debug_threads) { \ 155 pmix_output(0, "Releasing thread %s:%d", \ 156 __FILE__, __LINE__); \ 157 } \ 158 (lck)->active = false; \ 159 PMIX_POST_OBJECT(lck); \ 160 pmix_condition_broadcast(&(lck)->cond); \ 161 pmix_mutex_unlock(&(lck)->mutex); \ 162 } while(0) 163 #else 164 #define PMIX_RELEASE_THREAD(lck) \ 165 do { \ 166 (lck)->active = false; \ 167 PMIX_POST_OBJECT(lck); \ 168 pmix_condition_broadcast(&(lck)->cond); \ 169 pmix_mutex_unlock(&(lck)->mutex); \ 170 } while(0) 171 #endif 172 173 174 #define PMIX_WAKEUP_THREAD(lck) \ 175 do { \ 176 pmix_mutex_lock(&(lck)->mutex); \ 177 (lck)->active = false; \ 178 PMIX_POST_OBJECT(lck); \ 179 pmix_condition_broadcast(&(lck)->cond); \ 180 pmix_mutex_unlock(&(lck)->mutex); \ 181 } while(0) 182 183 184 /* provide a macro for forward-proofing the shifting 185 * of objects between threads - at some point, we 186 * may revamp our threading model */ 187 188 /* post an object to another thread - for now, we 189 * only have a memory barrier */ 190 #define PMIX_POST_OBJECT(o) pmix_atomic_wmb() 191 192 /* acquire an object from another thread - for now, 193 * we only have a memory barrier */ 194 #define PMIX_ACQUIRE_OBJECT(o) pmix_atomic_rmb() 195 196 197 PMIX_EXPORT int pmix_thread_start(pmix_thread_t *); 198 PMIX_EXPORT int pmix_thread_join(pmix_thread_t *, void **thread_return); 199 PMIX_EXPORT bool pmix_thread_self_compare(pmix_thread_t*); 200 PMIX_EXPORT pmix_thread_t *pmix_thread_get_self(void); 201 PMIX_EXPORT void pmix_thread_kill(pmix_thread_t *, int sig); 202 PMIX_EXPORT void pmix_thread_set_main(void); 203 204 END_C_DECLS 205 206 #endif /* PMIX_THREAD_H */ 207