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/stats.h>
00019 #include <libc/syscalls.h>
00020 #include <core/txdesc.h>
00021 #include <xcalls/xcalls.h>
00022
00023 typedef struct x_dup_undo_args_s x_dup_undo_args_t;
00024
00025 struct x_dup_undo_args_s {
00026 int fd;
00027 txc_koa_t *koa;
00028 };
00029
00030
00031 static
00032 void
00033 x_dup_undo(void *args, int *result)
00034 {
00035 int local_errno = 0;
00036 x_dup_undo_args_t *myargs = (x_dup_undo_args_t *) args;
00037 txc_koamgr_t *koamgr;
00038
00039 koamgr = txc_koa_get_koamgr(myargs->koa);
00040 txc_koa_lock_fd(koamgr, myargs->fd);
00041 txc_koa_detach_fd(myargs->koa, myargs->fd, 0);
00042 if (txc_libc_close(myargs->fd) < 0) {
00043 local_errno = errno;
00044 }
00045 txc_koa_unlock_fd(koamgr, myargs->fd);
00046 if (result) {
00047 *result = local_errno;
00048 }
00049 }
00050
00051
00066 int
00067 XCALL_DEF(x_dup)(int oldfd, int *result)
00068 {
00069 txc_tx_t *txd;
00070 txc_koamgr_t *koamgr = txc_g_koamgr;
00071 txc_koa_t *koa;
00072 txc_koa_t *koa2;
00073 txc_sentinel_t *sentinel;
00074 txc_result_t xret;
00075 int ret;
00076 int fildes;
00077 x_dup_undo_args_t *args_undo;
00078 int local_result;
00079
00080
00081 txd = txc_tx_get_txd();
00082
00083 switch(txc_tx_get_xactstate(txd)) {
00084 case TXC_XACTSTATE_TRANSACTIONAL_RETRYABLE:
00085 txc_koa_lock_fd(koamgr, oldfd);
00086 xret = txc_koa_lookup_fd2koa(koamgr, oldfd, &koa);
00087 if (xret == TXC_R_FAILURE) {
00088
00089
00090
00091
00092 local_result = EBADF;
00093 ret = -1;
00094 goto done;
00095 }
00096
00097
00098
00099
00100
00101
00102
00103 txc_koa_unlock_fd(koamgr, oldfd);
00104 txc_koa_lock_fds_refby_koa(koa);
00105 xret = txc_koa_lookup_fd2koa(koamgr, oldfd, &koa2);
00106 if (xret == TXC_R_FAILURE || koa != koa2) {
00107 local_result = EBADF;
00108 ret = -1;
00109 goto done;
00110 }
00111 sentinel = txc_koa_get_sentinel(koa);
00112 xret = txc_sentinel_tryacquire(txd, sentinel,
00113 TXC_SENTINEL_ACQUIREONRETRY);
00114 if (xret == TXC_R_BUSYSENTINEL) {
00115 txc_koa_unlock_fds_refby_koa(koa);
00116 txc_tx_abort_transaction(txd, TXC_ABORTREASON_BUSYSENTINEL);
00117 TXC_INTERNALERROR("Never gets here. Transaction abort failed.\n");
00118 }
00119
00120 if ((ret = fildes = txc_libc_dup(oldfd)) < 0) {
00121 txc_koa_unlock_fds_refby_koa(koa);
00122 local_result = errno;
00123 goto done;
00124 }
00125
00126 if ((args_undo = (x_dup_undo_args_t *)
00127 txc_buffer_linear_malloc(txd->buffer_linear,
00128 sizeof(x_dup_undo_args_t)))
00129 == NULL)
00130 {
00131 txc_libc_close(fildes);
00132 txc_koa_unlock_fds_refby_koa(koa);
00133 local_result = ENOMEM;
00134 ret = -1;
00135 goto done;
00136 }
00137 txc_koa_attach_fd(koa, fildes, 0);
00138 txc_koa_unlock_fds_refby_koa(koa);
00139
00140 args_undo->fd = fildes;
00141 args_undo->koa = koa;
00142
00143 txc_tx_register_undo_action(txd, x_dup_undo,
00144 (void *) args_undo, result,
00145 TXC_TX_REGULAR_UNDO_ACTION_ORDER);
00146 local_result = 0;
00147 ret = fildes;
00148 txc_stats_txstat_increment(txd, XCALL, x_dup, 1);
00149 goto done;
00150 case TXC_XACTSTATE_TRANSACTIONAL_IRREVOCABLE:
00151 case TXC_XACTSTATE_NONTRANSACTIONAL:
00152 xret = txc_koa_lookup_fd2koa(koamgr, oldfd, &koa);
00153 if (xret == TXC_R_FAILURE) {
00154
00155
00156
00157
00158 local_result = EBADF;
00159 ret = -1;
00160 goto done;
00161 }
00162 if ((ret = fildes = txc_libc_dup(oldfd)) < 0) {
00163 return ret;
00164 }
00165 txc_koa_lock_fds_refby_koa(koa);
00166 txc_koa_attach_fd(koa, fildes, 0);
00167 txc_koa_unlock_fds_refby_koa(koa);
00168 ret = fildes;
00169 break;
00170 default:
00171 TXC_INTERNALERROR("Unknown transaction state\n");
00172 }
00173
00174 done:
00175 if (result) {
00176 *result = local_result;
00177 }
00178 return ret;
00179 }