src/xcalls/x_pthread_create.c

Go to the documentation of this file.
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          * Don't let child thread execute start function by nullifying the 
00049          * start_routine pointer.
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         /* If start_routine is NULL then parent aborted so don't run child */
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 }

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7