src/xcalls/x_pipe.c

Go to the documentation of this file.
00001 
00007 #include <fcntl.h>
00008 #include <unistd.h>
00009 #include <errno.h>
00010 #include <string.h>
00011 #include <stdlib.h>
00012 #include <misc/debug.h>
00013 #include <misc/errno.h>
00014 #include <core/tx.h>
00015 #include <core/config.h>
00016 #include <core/koa.h>
00017 #include <core/buffer.h>
00018 #include <core/txdesc.h>
00019 #include <core/stats.h>
00020 #include <libc/syscalls.h>
00021 #include <xcalls/xcalls.h>
00022 
00023 
00024 typedef struct x_pipe_undo_args_s x_pipe_undo_args_t;
00025 
00026 struct x_pipe_undo_args_s {
00027         int       fd[2];
00028         txc_koa_t *koa[2];
00029 };
00030 
00031 
00032 static
00033 void
00034 x_pipe_undo(void *args, int *result)
00035 {
00036         int                local_errno = 0; 
00037         x_pipe_undo_args_t *myargs = (x_pipe_undo_args_t *) args;
00038         txc_koamgr_t       *koamgr;
00039 
00040         koamgr = txc_koa_get_koamgr(myargs->koa[0]);
00041         if (myargs->fd[0] < myargs->fd[1]) {
00042                 txc_koa_lock_fd(koamgr, myargs->fd[0]);
00043                 txc_koa_lock_fd(koamgr, myargs->fd[1]);
00044         } else {
00045                 txc_koa_lock_fd(koamgr, myargs->fd[1]);
00046                 txc_koa_lock_fd(koamgr, myargs->fd[0]);
00047         }
00048         txc_koa_detach_fd(myargs->koa[0], myargs->fd[0], 0);
00049         txc_koa_detach_fd(myargs->koa[1], myargs->fd[1], 0);
00050         if (txc_libc_close(myargs->fd[0]) < 0) {
00051                 local_errno = errno;
00052         }       
00053         if (txc_libc_close(myargs->fd[1]) < 0) {
00054                 local_errno = errno;
00055         }       
00056         txc_koa_unlock_fd(koamgr, myargs->fd[0]);
00057         txc_koa_unlock_fd(koamgr, myargs->fd[1]);
00058         if (result) {
00059                 *result = local_errno;
00060         }
00061 }
00062 
00063 
00078 int
00079 XCALL_DEF(x_pipe)(int fildes[2], int *result) 
00080 {
00081         txc_tx_t           *txd;
00082         txc_koamgr_t       *koamgr = txc_g_koamgr;
00083         txc_koa_t          *koa0;
00084         txc_koa_t          *koa1;
00085         txc_sentinel_t     *sentinel0;
00086         txc_sentinel_t     *sentinel1;
00087         txc_result_t       xret;
00088         int                ret;
00089         x_pipe_undo_args_t *args_undo; 
00090         int                local_result = 0;
00091 
00092         txd = txc_tx_get_txd();
00093 
00094         switch(txc_tx_get_xactstate(txd)) {
00095                 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00096                         if ((ret = txc_libc_pipe(fildes)) < 0) { 
00097                                 local_result = errno;
00098                                 goto done;
00099                         }
00100                         txc_koa_create(koamgr, &koa0, TXC_KOA_IS_PIPE_READ_END, NULL); 
00101                         txc_koa_create(koamgr, &koa1, TXC_KOA_IS_PIPE_WRITE_END, NULL);
00102                         /* Always acquire locks in increasing order to avoid any deadlock */
00103                         if (fildes[0] < fildes[1]) {
00104                                 txc_koa_lock_fd(koamgr, fildes[0]);
00105                                 txc_koa_lock_fd(koamgr, fildes[1]);
00106                         } else {
00107                                 txc_koa_lock_fd(koamgr, fildes[1]);
00108                                 txc_koa_lock_fd(koamgr, fildes[0]);
00109                         }
00110                         txc_koa_attach_fd(koa0, fildes[0], 0);
00111                         txc_koa_attach_fd(koa1, fildes[1], 0);
00112                         sentinel0 = txc_koa_get_sentinel(koa0);
00113                         xret = txc_sentinel_tryacquire(txd, sentinel0, 0);
00114                         if (xret != TXC_R_SUCCESS) {
00115                                 TXC_INTERNALERROR("Cannot acquire the sentinel of the KOA I've just created!\n");
00116                         }
00117                         sentinel1 = txc_koa_get_sentinel(koa1);
00118                         xret = txc_sentinel_tryacquire(txd, sentinel1, 0);
00119                         if (xret != TXC_R_SUCCESS) {
00120                                 TXC_INTERNALERROR("Cannot acquire the sentinel of the KOA I've just created!\n");
00121                         }
00122         
00123                         args_undo = (x_pipe_undo_args_t *)
00124                                     txc_buffer_linear_malloc(txd->buffer_linear, 
00125                                                              sizeof(x_pipe_undo_args_t));
00126                         if (args_undo == NULL) {
00127                                 TXC_INTERNALERROR("Allocation failed. Linear buffer out of space.\n");
00128                         }
00129                         args_undo->koa[0] = koa0;
00130                         args_undo->koa[1] = koa1;
00131                         args_undo->fd[0] = fildes[0];
00132                         args_undo->fd[1] = fildes[1];
00133 
00134                         txc_tx_register_undo_action  (txd, x_pipe_undo, 
00135                                                       (void *) args_undo, result,
00136                                                       TXC_KOA_CREATE_UNDO_ACTION_ORDER);
00137 
00138                         txc_koa_unlock_fd(koamgr, fildes[0]);
00139                         txc_koa_unlock_fd(koamgr, fildes[1]);
00140                         ret = 0;
00141                         txc_stats_txstat_increment(txd, XCALL, x_pipe, 1);
00142                         break;
00143                 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00144                 case TXC_XACTSTATE_NONTRANSACTIONAL:
00145                         /* 
00146                          * Even if xCalls don't provide transactional properties when called
00147                          * outside of a transaction, we still need to create a KOA and assign
00148                          * a sentinel to be used later by any transactional xCalls. Thus we
00149                          * still need to properly synchronize accesses to internal data
00150                          * structures.
00151                          */
00152                         if ((ret = txc_libc_pipe(fildes)) < 0) { 
00153                                 local_result = errno;
00154                                 goto done;
00155                         }
00156                         txc_koa_create(koamgr, &koa0, TXC_KOA_IS_PIPE_READ_END, NULL); 
00157                         txc_koa_create(koamgr, &koa1, TXC_KOA_IS_PIPE_WRITE_END, NULL);
00158                         /* Always acquire locks in increasing order to avoid any deadlock */
00159                         if (fildes[0] < fildes[1]) {
00160                                 txc_koa_lock_fd(koamgr, fildes[0]);
00161                                 txc_koa_lock_fd(koamgr, fildes[1]);
00162                         } else {
00163                                 txc_koa_lock_fd(koamgr, fildes[1]);
00164                                 txc_koa_lock_fd(koamgr, fildes[0]);
00165                         }
00166                         txc_koa_attach_fd(koa0, fildes[0], 0);
00167                         txc_koa_attach_fd(koa1, fildes[1], 0);
00168                         txc_koa_unlock_fd(koamgr, fildes[0]);
00169                         txc_koa_unlock_fd(koamgr, fildes[1]);
00170                         ret = 0;
00171         }
00172 done:
00173         if (result) {
00174                 *result = local_result;
00175         }
00176         return ret;
00177 }

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