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
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
00147
00148
00149
00150
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
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 }