00001 00007 #include <pthread.h> 00008 #include <core/tx.h> 00009 #include <core/config.h> 00010 #include <core/txdesc.h> 00011 #include <misc/debug.h> 00012 #include <misc/errno.h> 00013 #include <xcalls/xcalls.h> 00014 00015 typedef struct x_undo_args_s x_undo_args_t; 00016 00017 struct x_undo_args_s { 00018 pthread_mutex_t *mutex; 00019 }; 00020 00021 static 00022 void 00023 x_pthread_mutex_lock_undo(void *args, int *result) 00024 { 00025 x_undo_args_t *args_undo = (x_undo_args_t *) args; 00026 int local_result = 0; 00027 int ret; 00028 00029 if ((ret = pthread_mutex_unlock(args_undo->mutex)) != 0) { 00030 local_result = ret; 00031 } 00032 if (result) { 00033 *result = local_result; 00034 } 00035 } 00036 00051 int 00052 XCALL_DEF(x_pthread_mutex_lock)(pthread_mutex_t *mutex, int *result) 00053 { 00054 txc_tx_t *txd; 00055 int ret; 00056 x_undo_args_t *args_undo; 00057 int local_result = 0; 00058 00059 txd = txc_tx_get_txd(); 00060 00061 switch(txc_tx_get_xactstate(txd)) { 00062 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE: 00063 args_undo = (x_undo_args_t *) 00064 txc_buffer_linear_malloc(txd->buffer_linear, 00065 sizeof(x_undo_args_t)); 00066 if (args_undo == NULL) { 00067 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n"); 00068 } 00069 args_undo->mutex = mutex; 00070 if ((ret = pthread_mutex_trylock(mutex)) != 0) { 00071 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYTXLOCK); 00072 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n"); 00073 } 00074 00075 txc_tx_register_undo_action(txd, x_pthread_mutex_lock_undo, 00076 (void *) args_undo, result, 00077 TXC_TX_REGULAR_UNDO_ACTION_ORDER); 00078 00079 break; 00080 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE: 00081 case TXC_XACTSTATE_NONTRANSACTIONAL: 00082 if ((ret = pthread_mutex_lock(mutex)) != 0) { 00083 local_result = ret; 00084 goto done; 00085 } 00086 } 00087 done: 00088 if (result) { 00089 *result = local_result; 00090 } 00091 return ret; 00092 }