00001
00002 #ifndef ROSE_threadSupport_H
00003 #define ROSE_threadSupport_H
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "rosePublicConfig.h"
00026
00027 #include <assert.h>
00028 #include <stdint.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031
00032 #include <string>
00033
00034
00035 #ifdef ROSE_HAVE_PTHREAD_H
00036 # define ROSE_THREADS_ENABLED
00037 # define ROSE_THREADS_POSIX
00038 # include <pthread.h>
00039 #else
00040 # undef ROSE_THREADS_ENABLED
00041 #endif
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #ifndef ROSE_THREADS_ENABLED
00053 # ifdef _MSC_VER
00054 # pragma message("Multi-thread support is not enabled. ROSE will not be thread safe even for functions that advertise safety.")
00055 # else
00056 # warning "Multi-thread support is not enabled. ROSE will not be thread safe even for functions that advertise safety."
00057 # endif
00058 #endif
00059
00060
00061
00062
00063
00064
00087 enum RTS_Layer {
00088 RTS_LAYER_DONTCARE = 0,
00089
00090
00091 RTS_LAYER_ROSE_CALLBACKS_LIST_OBJ = 100,
00092 RTS_LAYER_RTS_MESSAGE_CLASS = 105,
00093 RTS_LAYER_DISASSEMBLER_CLASS = 110,
00095
00096
00097
00098
00099
00100
00101 RTS_LAYER_RSIM_SIGNALHANDLING_OBJ = 200,
00102 RTS_LAYER_RSIM_PROCESS_OBJ = 201,
00103 RTS_LAYER_RSIM_PROCESS_CLONE_OBJ = 202,
00104 RTS_LAYER_RSIM_THREAD_OBJ = 203,
00105 RTS_LAYER_RSIM_THREAD_CLASS = 204,
00106 RTS_LAYER_RSIM_SYSCALLDISABLER_OBJ = 205,
00107 RTS_LAYER_RSIM_TRACEIO_OBJ = 206,
00108 RTS_LAYER_RSIM_SIMULATOR_CLASS = 207,
00109 RTS_LAYER_RSIM_SIMULATOR_OBJ = 208,
00111
00112
00113 RTS_LAYER_USER_MIN = 250,
00114 RTS_LAYER_USER_MAX = 299,
00116
00117 RTS_LAYER_NLAYERS = 300
00118 };
00119
00126 bool RTS_acquiring(RTS_Layer);
00127
00130 void RTS_releasing(RTS_Layer);
00131
00132
00133
00134
00135
00155 #ifdef ROSE_THREADS_ENABLED
00156 # define RTS_MUTEX(MUTEX) \
00157 do { \
00158 RTS_mutex_t *RTS_Mp_mutex = &(MUTEX); \
00159 int RTS_Mp_err = RTS_mutex_lock(RTS_Mp_mutex); \
00160 assert(0==RTS_Mp_err); \
00161 do { \
00162 try {
00163
00165 # define RTS_MUTEX_END \
00166 } catch (...) { \
00167 RTS_Mp_err = RTS_mutex_unlock(RTS_Mp_mutex); \
00168 assert(0==RTS_Mp_err); \
00169 throw; \
00170 } \
00171 } while (0); \
00172 RTS_Mp_err = RTS_mutex_unlock(RTS_Mp_mutex); \
00173 assert(0==RTS_Mp_err); \
00174 } while (0)
00175 #else
00176 # define RTS_MUTEX(MUTEX) \
00177 do {
00178 # define RTS_MUTEX_END \
00179 } while (0)
00180 #endif
00181
00182
00183
00184
00185
00186 #define RTS_MUTEX_MAGIC 0x1a95a713
00187
00188 #ifdef ROSE_THREADS_ENABLED
00189
00194 struct RTS_mutex_t {
00195 unsigned magic;
00196 RTS_Layer layer;
00197 pthread_mutex_t mutex;
00198 };
00199
00200 #define RTS_MUTEX_INITIALIZER(LAYER) { RTS_MUTEX_MAGIC, (LAYER), PTHREAD_MUTEX_INITIALIZER }
00201
00203 int RTS_mutex_init(RTS_mutex_t*, RTS_Layer, pthread_mutexattr_t*);
00204
00205 #else
00206
00207 struct RTS_mutex_t {
00208 int dummy;
00209 };
00210
00211 #define RTS_MUTEX_INITIALIZER(LAYER) { 0 }
00212
00213 int RTS_mutex_init(RTS_mutex_t*, RTS_Layer, void*);
00214
00215 #endif
00216
00218 int RTS_mutex_lock(RTS_mutex_t*);
00219
00221 int RTS_mutex_unlock(RTS_mutex_t*);
00222
00223
00224
00225
00226
00227
00228
00229
00313 #ifdef ROSE_THREADS_ENABLED
00314 # define RTS_RWLOCK(RWLOCK, HOW) \
00315 do { \
00316 RTS_rwlock_t *RTS_Wp_rwlock = &(RWLOCK); \
00317 int RTS_Wp_err = RTS_rwlock_##HOW(RTS_Wp_rwlock); \
00318 assert(0==RTS_Wp_err); \
00319 do { \
00320 try {
00321
00322 # define RTS_RWLOCK_END \
00323 } catch (...) { \
00324 RTS_Wp_err = RTS_rwlock_unlock(RTS_Wp_rwlock); \
00325 assert(0==RTS_Wp_err); \
00326 throw; \
00327 } \
00328 } while (0); \
00329 RTS_Wp_err = RTS_rwlock_unlock(RTS_Wp_rwlock); \
00330 assert(0==RTS_Wp_err); \
00331 } while (0)
00332
00333 #else
00334 # define RTS_RWLOCK(RWLOCK, HOW) \
00335 do {
00336 # define RTS_RWLOCK_END \
00337 } while (0)
00338 #endif
00339
00340 #define RTS_READ(RWLOCK) RTS_RWLOCK(RWLOCK, rdlock)
00341 #define RTS_READ_END RTS_RWLOCK_END
00342 #define RTS_WRITE(RWLOCK) RTS_RWLOCK(RWLOCK, wrlock)
00343 #define RTS_WRITE_END RTS_RWLOCK_END
00345
00346
00347
00348
00349
00350
00351
00352
00356 #ifdef ROSE_THREADS_ENABLED
00357 struct RTS_rwlock_t {
00358 unsigned magic;
00359 RTS_Layer layer;
00360 pthread_rwlock_t rwlock;
00361 RTS_mutex_t mutex;
00362 size_t nlocks;
00363 pthread_t owner;
00364 };
00365 #else
00366 struct RTS_rwlock_t {
00367 int dummy;
00368 };
00369 #endif
00370
00371 #define RTS_RWLOCK_MAGIC 0x20e7f3f4
00372
00374 #ifdef ROSE_THREADS_ENABLED
00375 # define RTS_RWLOCK_INITIALIZER(LAYER) { RTS_RWLOCK_MAGIC, \
00376 (LAYER), \
00377 PTHREAD_RWLOCK_INITIALIZER, \
00378 RTS_MUTEX_INITIALIZER(RTS_LAYER_DONTCARE), \
00379 0 \
00380 }
00381 #else
00382 # define RTS_RWLOCK_INITIALIZER(LAYER) { 0 }
00383 #endif
00384
00385 #ifdef ROSE_THREADS_ENABLED
00386
00387 int RTS_rwlock_init(RTS_rwlock_t *rwlock, RTS_Layer, pthread_rwlockattr_t *wrlock_attrs);
00388 #else
00389 int RTS_rwlock_init(RTS_rwlock_t *rwlock, RTS_Layer, void *wrlock_attrs);
00390 #endif
00391
00405 int RTS_rwlock_rdlock(RTS_rwlock_t *rwlock);
00406
00423 int RTS_rwlock_wrlock(RTS_rwlock_t *rwlock);
00424
00436 int RTS_rwlock_unlock(RTS_rwlock_t *rwlock);
00437
00438
00439
00440
00441
00442
00443
00444
00480 #ifdef ROSE_THREADS_ENABLED
00481 # define RTS_INIT(MUTEX, ALLOW_RECURSION) \
00482 do { \
00483 static bool RTS_Is_initialized=false, RTS_Is_initializing=false; \
00484 static pthread_t RTS_Is_initializer; \
00485 static pthread_cond_t RTS_Is_condition=PTHREAD_COND_INITIALIZER; \
00486 RTS_mutex_t *RTS_Ip_mutex = &(MUTEX); \
00487 bool RTS_Ip_initialized, RTS_Ip_initializing; \
00488 bool RTS_Ip_allow_recursion = (ALLOW_RECURSION); \
00489 \
00490
00491
00492 \
00493 RTS_MUTEX(MUTEX) { \
00494 if (!(RTS_Ip_initialized=RTS_Is_initialized) && !(RTS_Ip_initializing=RTS_Is_initializing)) { \
00495 RTS_Is_initializing = true; \
00496 RTS_Is_initializer = pthread_self(); \
00497 } \
00498 } RTS_MUTEX_END; \
00499 \
00500 if (!RTS_Ip_initialized) { \
00501 if (!RTS_Ip_initializing) { \
00502 do { \
00503 try {
00504
00505
00507 # define RTS_INIT_END \
00508 } catch (...) { \
00509 \
00510 RTS_MUTEX(*RTS_Ip_mutex) { \
00511 RTS_Is_initialized = true; \
00512 RTS_Is_initializing = false; \
00513 pthread_cond_broadcast(&RTS_Is_condition); \
00514 } RTS_MUTEX_END; \
00515 throw; \
00516 } \
00517 } while (0); \
00518 RTS_MUTEX(*RTS_Ip_mutex) { \
00519 RTS_Is_initialized = true; \
00520 RTS_Is_initializing = false; \
00521 pthread_cond_broadcast(&RTS_Is_condition); \
00522 } RTS_MUTEX_END; \
00523 } else if (pthread_equal(pthread_self(), RTS_Is_initializer)) { \
00524
00525
00526
00527 \
00528 if (!RTS_Ip_allow_recursion) { \
00529 fprintf(stderr, "RTS_I_LOCK body made a recursive call. Aborting...\n"); \
00530 abort(); \
00531 } \
00532 } else { \
00533
00534 \
00535 RTS_MUTEX(*RTS_Ip_mutex) { \
00536 while (!RTS_Is_initialized) \
00537 pthread_cond_wait(&RTS_Is_condition, &(RTS_Ip_mutex->mutex)); \
00538 } RTS_MUTEX_END; \
00539 } \
00540 } \
00541 } while (0)
00542 #else
00543 # define RTS_INIT(MUTEX, ALLOW_RECURSION) \
00544 do { \
00545 static bool RTS_Is_initialized=false; \
00546 if (!RTS_Is_initialized) { \
00547 RTS_Is_initialized = true; \
00548 do {
00549 # define RTS_INIT_END \
00550 } while (0); \
00551 } \
00552 } while (0)
00553 #endif
00554
00555 #define RTS_INIT_RECURSIVE(MUTEX) RTS_INIT(MUTEX, true)
00556 #define RTS_INIT_NONRECURSIVE(MUTEX) RTS_INIT(MUTEX, false)
00559
00560
00561
00562
00573 class RTS_Message {
00574 public:
00578 class Prefix {
00579 public:
00580 virtual ~Prefix() {};
00581 virtual void operator()(FILE*) {}
00582 };
00583
00594 RTS_Message(FILE *f, Prefix *p)
00595 : f(f), p(p), buffer(NULL), bufsz(0), interrupted(false) {
00596 ctor();
00597 }
00598
00599 ~RTS_Message() {
00600 dtor();
00601 }
00602
00604 void set_file(FILE *f) {
00605 this->f = f;
00606 }
00607
00609 FILE *get_file() const {
00610 return f;
00611 }
00612
00633 RTS_Message& multipart(const std::string &name, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
00634
00647 RTS_Message& more(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
00648
00652 void multipart_end();
00653
00667 RTS_Message& mesg(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
00668
00683 RTS_Message& brief(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
00684
00688 void brief_begin(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
00689
00691 void brief_end(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
00692
00703 int lock();
00704
00710 int unlock(bool sol=true);
00711
00712 private:
00713 RTS_Message() {abort();}
00714 RTS_Message& operator=(RTS_Message&) { abort(); return *this; }
00715 void ctor();
00716 void dtor();
00717 void terminate();
00718 void prefix();
00719 void output_lines(const char *s);
00720 void format(const char *fmt, va_list, va_list);
00722 static RTS_rwlock_t rwlock;
00723 static RTS_Message *in_multi;
00724 static bool sol;
00726 FILE *f;
00727 Prefix *p;
00728 char *buffer;
00729 size_t bufsz;
00730 std::string name;
00731 bool interrupted;
00732 };
00733
00734
00735
00736
00737
00771 #ifdef ROSE_THREADS_ENABLED
00772 # define RTS_MESSAGE(MESG) \
00773 do { \
00774 RTS_Message *RTS_Mp_mesg = &(MESG); \
00775 int RTS_Mp_err = RTS_Mp_mesg->lock(); \
00776 assert(0==RTS_Mp_err); \
00777 do { \
00778 try {
00779
00780 # define RTS_MESSAGE_END(SOL) \
00781 } catch (...) { \
00782 RTS_Mp_err = RTS_Mp_mesg->unlock((SOL)); \
00783 assert(0==RTS_Mp_err); \
00784 throw; \
00785 } \
00786 } while (0); \
00787 RTS_Mp_err = RTS_Mp_mesg->unlock((SOL)); \
00788 assert(0==RTS_Mp_err); \
00789 } while (0)
00790 #else
00791 # define RTS_MESSAGE(MESG) \
00792 do {
00793 # define RTS_MESSAGE_END(SOL) \
00794 } while (0)
00795 #endif
00796
00800 #endif