ROSE
0.9.6a
|
#include "rosePublicConfig.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <pthread.h>
Go to the source code of this file.
Classes | |
struct | RTS_mutex_t |
Mutual exclusion lock. More... | |
struct | RTS_rwlock_t |
A read-write lock for ROSE Thread Support. More... | |
class | RTS_Message |
Support for messages in a multi-threaded program. More... | |
class | RTS_Message::Prefix |
The Prefix class is used to generate prefix text for every line of output. More... | |
Macros | |
#define | ROSE_THREADS_ENABLED |
#define | ROSE_THREADS_POSIX |
#define | __attribute__(x) /*NOTHING*/ |
#define | __attribute(x) /*NOTHING*/ |
#define | RTS_MUTEX(MUTEX) |
Protect a critical section with a mutual exclusion lock. More... | |
#define | RTS_MUTEX_END |
End an RTS_MUTEX construct. More... | |
#define | RTS_MUTEX_MAGIC 0x1a95a713 |
#define | RTS_MUTEX_INITIALIZER(LAYER) { RTS_MUTEX_MAGIC, (LAYER), PTHREAD_MUTEX_INITIALIZER } |
#define | RTS_RWLOCK(RWLOCK, HOW) |
Protect a critical section with a read-write lock. More... | |
#define | RTS_RWLOCK_END |
#define | RTS_READ(RWLOCK) RTS_RWLOCK(RWLOCK, rdlock) |
See RTS_RWLOCK. More... | |
#define | RTS_READ_END RTS_RWLOCK_END |
See RTS_RWLOCK. More... | |
#define | RTS_WRITE(RWLOCK) RTS_RWLOCK(RWLOCK, wrlock) |
See RTS_RWLOCK. More... | |
#define | RTS_WRITE_END RTS_RWLOCK_END |
See RTS_RWLOCK. More... | |
#define | RTS_RWLOCK_MAGIC 0x20e7f3f4 |
#define | RTS_RWLOCK_INITIALIZER(LAYER) |
Static initializer for an RTS_rwlock_t instance, similar in nature to PTHREAD_RWLOCK_INITIALIZER. More... | |
#define | RTS_INIT(MUTEX, ALLOW_RECURSION) |
Initializer synchronization. More... | |
#define | RTS_INIT_END |
End an RTS_INIT construct. More... | |
#define | RTS_INIT_RECURSIVE(MUTEX) RTS_INIT(MUTEX, true) |
See RTS_INIT. More... | |
#define | RTS_INIT_NONRECURSIVE(MUTEX) RTS_INIT(MUTEX, false) |
See RTS_INIT. More... | |
#define | RTS_MESSAGE(MESG) |
Provides a locked context for messaging. More... | |
#define | RTS_MESSAGE_END(SOL) |
Provides a locked context for messaging. More... | |
Enumerations | |
enum | RTS_Layer { RTS_LAYER_DONTCARE = 0, RTS_LAYER_ROSE_CALLBACKS_LIST_OBJ = 100, RTS_LAYER_RTS_MESSAGE_CLASS = 105, RTS_LAYER_DISASSEMBLER_CLASS = 110, RTS_LAYER_ROSE_SMT_SOLVERS = 115, RTS_LAYER_RSIM_SIGNALHANDLING_OBJ = 200, RTS_LAYER_RSIM_PROCESS_OBJ = 201, RTS_LAYER_RSIM_PROCESS_CLONE_OBJ = 202, RTS_LAYER_RSIM_THREAD_OBJ = 203, RTS_LAYER_RSIM_THREAD_CLASS = 204, RTS_LAYER_RSIM_SYSCALLDISABLER_OBJ = 205, RTS_LAYER_RSIM_TRACEIO_OBJ = 206, RTS_LAYER_RSIM_SIMULATOR_CLASS = 207, RTS_LAYER_RSIM_SIMULATOR_OBJ = 208, RTS_LAYER_USER_MIN = 250, RTS_LAYER_USER_MAX = 299, RTS_LAYER_NLAYERS = 300 } |
Layers where syncrhonization primitives are defined. More... | |
Functions | |
bool | RTS_acquiring (RTS_Layer) |
Check for layering violations. More... | |
void | RTS_releasing (RTS_Layer) |
Notes the release of a lock. More... | |
int | RTS_mutex_init (RTS_mutex_t *, RTS_Layer, pthread_mutexattr_t *) |
Initialize a mutual exclusion lock. More... | |
int | RTS_mutex_lock (RTS_mutex_t *) |
Obtain an exclusive lock. More... | |
int | RTS_mutex_unlock (RTS_mutex_t *) |
Release an exclusive lock. More... | |
int | RTS_rwlock_init (RTS_rwlock_t *rwlock, RTS_Layer, pthread_rwlockattr_t *wrlock_attrs) |
Intializes an RTS_rwlock_t in a manner similar to pthread_rwlock_init(). More... | |
int | RTS_rwlock_rdlock (RTS_rwlock_t *rwlock) |
Obtain a read lock. More... | |
int | RTS_rwlock_wrlock (RTS_rwlock_t *rwlock) |
Obtain a write lock. More... | |
int | RTS_rwlock_unlock (RTS_rwlock_t *rwlock) |
Release a read or write lock. More... | |
#define ROSE_THREADS_ENABLED |
Definition at line 36 of file threadSupport.h.
#define ROSE_THREADS_POSIX |
Definition at line 37 of file threadSupport.h.
#define __attribute__ | ( | x) | /*NOTHING*/ |
Definition at line 62 of file threadSupport.h.
#define __attribute | ( | x) | /*NOTHING*/ |
Definition at line 63 of file threadSupport.h.
#define RTS_MUTEX | ( | MUTEX) |
Protect a critical section with a mutual exclusion lock.
This macro should be used within ROSE whenever we need to obtain a lock for a critical section. The critical section should end with a matching RTS_MUTEX_END macro. The suggested code style is to use curly braces and indentation to help visually line up the RTS_MUTEX with the RTS_MUTEX_END, such as:
The critical section should not exit the construct except through the RTS_MUTEX_END macro. In other words, the critical section should not have "return" statements, longjmps, or any "goto" that branches outside the critical section. However, "break" statements and exceptions are supported.
If the mutex is an error checking mutex then ROSE will assert that the lock is not already held by this thread. If the mutex is recursive then the lock will be obtained recursively if necessary.
Definition at line 162 of file threadSupport.h.
Referenced by ROSE_Callbacks::List< T >::after(), ROSE_Callbacks::List< T >::append(), ROSE_Callbacks::List< T >::before(), ROSE_Callbacks::List< T >::callbacks(), ROSE_Callbacks::List< T >::clear(), ROSE_Callbacks::List< T >::empty(), ROSE_Callbacks::List< T >::erase(), Disassembler::lookup(), ROSE_Callbacks::List< T >::prepend(), Disassembler::progress(), Disassembler::register_subclass(), ROSE_Callbacks::List< T >::replace(), Disassembler::set_progress_reporting(), and ROSE_Callbacks::List< T >::size().
#define RTS_MUTEX_END |
End an RTS_MUTEX construct.
Definition at line 171 of file threadSupport.h.
Referenced by ROSE_Callbacks::List< T >::after(), ROSE_Callbacks::List< T >::append(), ROSE_Callbacks::List< T >::before(), ROSE_Callbacks::List< T >::callbacks(), ROSE_Callbacks::List< T >::clear(), ROSE_Callbacks::List< T >::empty(), ROSE_Callbacks::List< T >::erase(), Disassembler::lookup(), ROSE_Callbacks::List< T >::prepend(), Disassembler::progress(), Disassembler::register_subclass(), ROSE_Callbacks::List< T >::replace(), Disassembler::set_progress_reporting(), and ROSE_Callbacks::List< T >::size().
#define RTS_MUTEX_MAGIC 0x1a95a713 |
Definition at line 192 of file threadSupport.h.
#define RTS_MUTEX_INITIALIZER | ( | LAYER) | { RTS_MUTEX_MAGIC, (LAYER), PTHREAD_MUTEX_INITIALIZER } |
Definition at line 206 of file threadSupport.h.
#define RTS_RWLOCK | ( | RWLOCK, | |
HOW | |||
) |
Protect a critical section with a read-write lock.
These macros should be used within ROSE whenever we need to protect a critical section among two kinds of access: reading and writing.
This construct allows at most one thread to hold a write lock, or multiple threads to hold read locks. Write locks are granted only when no other thread holds a read or write lock, and a request for a write lock blocks (becomes pending) if the lock cannot be granted. Read locks are granted only when no write lock is already granted to another thread, and no write lock is pending.
Like POSIX read-write locks, RTS_rwlock_t allows a single thread to obtain multiple read locks recursively. Unlike POSIX read-write locks, RTS_rwlock_t also allows the following:
In particular, this implementation does not allow a thread which holds only read locks to be granted a write lock (i.e., no lock upgrading). Like POSIX read-write locks, this situation will lead to deadlock.
The RTS_READ macro should be paired with an RTS_READ_END macro; the RTS_WRITE macro should be paired with an RTS_WRITE_END macro. The RTS_RWLOCK macro is a generalization of RTS_READ and RTS_WRITE where its second argument is either the word "rdlock" or "wrlock", respectively. It should be paired with an RTS_RWLOCK_END macro.
The critical section may exit only via "break" statement, throwing an exception, or falling through the end. Exceptions thrown by the critical section will release the lock before rethrowing the exception.
A simple example demonstrating how locks can be obtained recursively. Any number of threads can be operating on a single, common object concurrently and each of the four defined operations remains atomic.
Definition at line 320 of file threadSupport.h.
#define RTS_RWLOCK_END |
Definition at line 328 of file threadSupport.h.
#define RTS_READ | ( | RWLOCK) | RTS_RWLOCK(RWLOCK, rdlock) |
See RTS_RWLOCK.
Definition at line 346 of file threadSupport.h.
#define RTS_READ_END RTS_RWLOCK_END |
See RTS_RWLOCK.
Definition at line 347 of file threadSupport.h.
#define RTS_WRITE | ( | RWLOCK) | RTS_RWLOCK(RWLOCK, wrlock) |
See RTS_RWLOCK.
Definition at line 348 of file threadSupport.h.
#define RTS_WRITE_END RTS_RWLOCK_END |
See RTS_RWLOCK.
Definition at line 349 of file threadSupport.h.
#define RTS_RWLOCK_MAGIC 0x20e7f3f4 |
Definition at line 377 of file threadSupport.h.
#define RTS_RWLOCK_INITIALIZER | ( | LAYER) |
Static initializer for an RTS_rwlock_t instance, similar in nature to PTHREAD_RWLOCK_INITIALIZER.
Definition at line 381 of file threadSupport.h.
#define RTS_INIT | ( | MUTEX, | |
ALLOW_RECURSION | |||
) |
Initializer synchronization.
Sometimes we want a critical section to be executed only by the first thread to call the function and all other threads that might call the same function should block until the first caller completes. These macros can be used for that purpose.
The MUTEX is briefly locked to inspect the state of initilization, and then unlocked before the user-supplied body is executed. The user is permitted to obtain the mutex lock again in the body if desired, although this is only necessary if other code paths (outside the RTS_INIT construct) might interfere with the body.
If ALLOW_RECURSION is true, then a recursive call from the body will jump over the RTS_INIT construct without doing anything (other than briefly obtaining the mutex lock to inspect the state of initialization). Otherwise a recursive call from the body is considered a logic error and the process will be aborted. For convenience, we define two additional macros, RTS_INIT_RECURSIVE and RTS_INIT_NONRECURSIVE, which may be used in place of the two-argument RTS_INIT macro.
The user-supplied body may exit prematurely either by a "break" statement or by throwing an exception. In either case, the initialization is assumed to have completed and the body will not be executed by any other future call. Any other kind of premature exit from the body (return, goto, longjmp, etc) results in undefined behavior.
Example code. Consider a class method which is responsible for one-time initialization of certain class data structures. This initialization function is called by nearly every other method in the class, and therefore anything that the initialization function does might result in a recursive call to the initializer.
Definition at line 487 of file threadSupport.h.
#define RTS_INIT_END |
End an RTS_INIT construct.
Definition at line 513 of file threadSupport.h.
Referenced by Disassembler::initclass().
#define RTS_INIT_RECURSIVE | ( | MUTEX) | RTS_INIT(MUTEX, true) |
See RTS_INIT.
Definition at line 561 of file threadSupport.h.
Referenced by Disassembler::initclass().
#define RTS_INIT_NONRECURSIVE | ( | MUTEX) | RTS_INIT(MUTEX, false) |
See RTS_INIT.
Definition at line 562 of file threadSupport.h.
#define RTS_MESSAGE | ( | MESG) |
Provides a locked context for messaging.
Normal message output methods do not require locking since they perform the locking implicitly. However, one needs to provide some kind of customized output not otherwise possible, a lock needs to be obtained while that output is produced. See RTS_Messsage::lock() for details.
The RTS_MESSAGE macro takes an RTS_Message object as an argument, and locks it until the corresponding RTS_MESSAGE_END macro. The RTS_MESSAGE_END macro takes one argument: a Boolean expression which evaluates to true if no output was produced or the output ended with a line-feed.
The body between the RTS_MESSAGE and RTS_MESSAGE_END macro should not exit non-locally except by "break" or throwing an exception, both of which release the lock.
Example:
Note that the previous example could have more easily been obtained with the following, except that in a multi-threaded application another thread might interject its own output between these lines.
Definition at line 778 of file threadSupport.h.
#define RTS_MESSAGE_END | ( | SOL) |
Provides a locked context for messaging.
Normal message output methods do not require locking since they perform the locking implicitly. However, one needs to provide some kind of customized output not otherwise possible, a lock needs to be obtained while that output is produced. See RTS_Messsage::lock() for details.
The RTS_MESSAGE macro takes an RTS_Message object as an argument, and locks it until the corresponding RTS_MESSAGE_END macro. The RTS_MESSAGE_END macro takes one argument: a Boolean expression which evaluates to true if no output was produced or the output ended with a line-feed.
The body between the RTS_MESSAGE and RTS_MESSAGE_END macro should not exit non-locally except by "break" or throwing an exception, both of which release the lock.
Example:
Note that the previous example could have more easily been obtained with the following, except that in a multi-threaded application another thread might interject its own output between these lines.
Definition at line 786 of file threadSupport.h.
enum RTS_Layer |
Layers where syncrhonization primitives are defined.
When a thread intends to acquire multiple locks at a time, it must acquire those locks in a particular order to prevent deadlock. Deadlock can occur when thread 1 attempts to acquire lock A and then B, while thread 2 attempts to acquire lock B and then A. By defining every lock to belong to a particular software layer, we can impose a partial ordering on the locks and enforce the requirement that a thread obtain locks in that order. To use the previous example, if lock A belongs to layer X and lock B to layer Y, then a rule that says "locks of layer X must be acquired before locks of layer Y when attempting to acquire both at once" would be sufficient to prevent deadlock. This mechanism makes no attempt to define an acquisition order for locks of the same layer (at least not at this time).
When a thread acquires locks from more than one layer at a time, they must be acquired in descending order by layer (they can be released in any order). If a thread attempts to aquire a lock whose layer is greater than the minimum layer for which it already holds a lock, then an error message is emitted and the process aborts.
New layers can be added to this enum and the RTS_LAYER_NLAYERS constant can be increased if necessary. When a layer's number is changed, all of ROSE must be recompiled. The constant name is used in error messages. Names ending with "_CLASS" refer to synchronization primities that are class data members (or global), while those ending with "_OBJ" belong to a particular object.
Layer zero is special and is the default layer for all syncronization primitives not explicitly associated with any layer. Locks in layer zero can be acquired in any order without generating an error message (so silent deadlock is a distinct possibility).
Enumerator | |
---|---|
RTS_LAYER_DONTCARE | |
RTS_LAYER_ROSE_CALLBACKS_LIST_OBJ |
ROSE_Callbacks::List class. |
RTS_LAYER_RTS_MESSAGE_CLASS |
RTS_Message class. |
RTS_LAYER_DISASSEMBLER_CLASS |
Disassembler class. |
RTS_LAYER_ROSE_SMT_SOLVERS |
SMTSolver class. |
RTS_LAYER_RSIM_SIGNALHANDLING_OBJ |
RSIM_SignalHandling. |
RTS_LAYER_RSIM_PROCESS_OBJ |
RSIM_Process. |
RTS_LAYER_RSIM_PROCESS_CLONE_OBJ |
RSIM_Process::Clone. |
RTS_LAYER_RSIM_THREAD_OBJ |
RSIM_Thread. |
RTS_LAYER_RSIM_THREAD_CLASS |
RSIM_Thread. |
RTS_LAYER_RSIM_SYSCALLDISABLER_OBJ |
RSIM_Adapter::SyscallDisabler. |
RTS_LAYER_RSIM_TRACEIO_OBJ |
RSIM_Adapter::TraceIO. |
RTS_LAYER_RSIM_SIMULATOR_CLASS |
RSIM_Simulator. |
RTS_LAYER_RSIM_SIMULATOR_OBJ |
RSIM_Simulator. |
RTS_LAYER_USER_MIN |
Minimum layer for end-user usage. |
RTS_LAYER_USER_MAX |
Maximum layer for end-user usage. |
RTS_LAYER_NLAYERS |
Definition at line 92 of file threadSupport.h.
bool RTS_acquiring | ( | RTS_Layer | ) |
Check for layering violations.
This should be called just before any attempt to acquire a lock. The specified layer should be the layer of the lock being acquired. Returns true if it is OK to acquire the lock, false if doing so could result in deadlock. Before returning false, an error message is printed to stderr.
Note that this function is a no-op when the compiler does not support the "__thread" type qualifier, nor any other qualifier as detected by the ROSE configure script. Currently, this is a no-op on Mac OS X. [RPM 2011-05-04]
void RTS_releasing | ( | RTS_Layer | ) |
Notes the release of a lock.
This function should be called before or after each release of a lock. The layer number is that of the lock which is release.
int RTS_mutex_init | ( | RTS_mutex_t * | , |
RTS_Layer | , | ||
pthread_mutexattr_t * | |||
) |
Initialize a mutual exclusion lock.
Referenced by ROSE_Callbacks::List< T >::List().
int RTS_mutex_lock | ( | RTS_mutex_t * | ) |
Obtain an exclusive lock.
Behavior is similar to pthread_mutex_lock(). Returns zero on success, errno on failure.
int RTS_mutex_unlock | ( | RTS_mutex_t * | ) |
Release an exclusive lock.
Behavior is similar to pthread_mutex_unlock(). Returns zero on success, errno on failure.
int RTS_rwlock_init | ( | RTS_rwlock_t * | rwlock, |
RTS_Layer | , | ||
pthread_rwlockattr_t * | wrlock_attrs | ||
) |
Intializes an RTS_rwlock_t in a manner similar to pthread_rwlock_init().
int RTS_rwlock_rdlock | ( | RTS_rwlock_t * | rwlock) |
Obtain a read lock.
The semantics are identical to pthread_rwlock_rdlock() documented in "The Open Group Base Specifications Issue 6: IEEE Std 1003.1, 2004 Edition" [1] with the following changes:
[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_rwlock_rdlock.html
int RTS_rwlock_wrlock | ( | RTS_rwlock_t * | rwlock) |
Obtain a write lock.
The semantics are identical to pthread_rwlock_wrlock() documented in "The Open Group Base Specifications Issue 6: IEEE Std 1003.1, 2004 Edition" [1] with the following changes:
Note that a write lock will not be granted if a thread already holds only read locks. Attempting to obtain a write lock in this situation will result in deadlock.
[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_rwlock_wrlock.html
int RTS_rwlock_unlock | ( | RTS_rwlock_t * | rwlock) |
Release a read or write lock.
The semantics are identical to pthread_rwlock_unlock() documented in "The Open Group Base Specification Issue 6: IEEE Std 1003.1, 2004 Edition" [1] with the following additions:
[1] http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_rwlock_unlock.html