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 <misc/malloc.h>
00014 #include <xcalls/xcalls.h>
00015
00016 typedef struct x_pthread_create_control_block_s x_pthread_create_control_block_t;
00017
00018 struct x_pthread_create_control_block_s {
00019 pthread_mutex_t start_lock;
00020 volatile void *(*start)(void *);
00021 void *arg;
00022 };
00023
00024
00025 static
00026 void
00027 x_pthread_create_commit(void *args, int *result)
00028 {
00029 x_pthread_create_control_block_t *control_block = (x_pthread_create_control_block_t *) args;
00030 int local_result = 0;
00031
00032 pthread_mutex_unlock(&control_block->start_lock);
00033
00034 if (result) {
00035 *result = local_result;
00036 }
00037 }
00038
00039
00040 static
00041 void
00042 x_pthread_create_undo(void *args, int *result)
00043 {
00044 x_pthread_create_control_block_t *control_block = (x_pthread_create_control_block_t *) args;
00045 int local_result = 0;
00046
00047
00048
00049
00050
00051 control_block->start = NULL;
00052 pthread_mutex_unlock(&control_block->start_lock);
00053
00054 if (result) {
00055 *result = local_result;
00056 }
00057 }
00058
00059
00060
00061 static
00062 void *
00063 x_pthread_create_start_indirection(void *args)
00064 {
00065 void *(*start_routine)(void *);
00066 void *myarg;
00067 x_pthread_create_control_block_t *control_block = (x_pthread_create_control_block_t *) args;
00068
00069 myarg = control_block->arg;
00070 pthread_mutex_lock(&control_block->start_lock);
00071 start_routine = control_block->start;
00072 FREE(control_block);
00073
00074 if (start_routine) {
00075 return start_routine(myarg);
00076 } else {
00077 return (void *) 0x0;
00078 }
00079 }
00080
00081
00098 int
00099 XCALL_DEF(x_pthread_create)(pthread_t *thread,
00100 const pthread_attr_t *attr,
00101 void *(*start_routine)(void*),
00102 void *arg,
00103 int *result)
00104 {
00105 txc_tx_t *txd;
00106 int ret;
00107 x_pthread_create_control_block_t *control_block;
00108 int local_result = 0;
00109
00110 txd = txc_tx_get_txd();
00111
00112 switch(txc_tx_get_xactstate(txd)) {
00113 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00114 control_block = (x_pthread_create_control_block_t *) MALLOC(sizeof(x_pthread_create_control_block_t));
00115
00116 control_block->arg = arg;
00117 control_block->start = start_routine;
00118 pthread_mutex_init(&control_block->start_lock, NULL);
00119 pthread_mutex_lock(&control_block->start_lock);
00120 pthread_create(thread, attr, x_pthread_create_start_indirection, (void *) control_block);
00121
00122 txc_tx_register_commit_action(txd, x_pthread_create_commit,
00123 (void *) control_block, result,
00124 TXC_TX_REGULAR_COMMIT_ACTION_ORDER);
00125 txc_tx_register_undo_action(txd, x_pthread_create_undo,
00126 (void *) control_block, result,
00127 TXC_TX_REGULAR_UNDO_ACTION_ORDER);
00128
00129 ret = 0;
00130 break;
00131 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00132 case TXC_XACTSTATE_NONTRANSACTIONAL:
00133 if ((ret = pthread_create(thread, attr, start_routine, arg)) != 0) {
00134 local_result = ret;
00135 goto done;
00136 }
00137 }
00138 done:
00139 if (result) {
00140 *result = local_result;
00141 }
00142 return ret;
00143 }