int attribute_hidden __pthread_enable_asynccancel (void) { struct pthread *self = THREAD_SELF; int oldval; if (is_recording()) { pthread_log_record (0, PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling, 1); oldval = THREAD_GETMEM (self, cancelhandling); pthread_log_record (oldval, PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling, 0); } else if (is_replaying()) { pthread_log_replay (PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling); oldval = pthread_log_replay (PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling); } else { oldval = THREAD_GETMEM (self, cancelhandling); } while (1) { int newval = oldval | CANCELTYPE_BITMASK; if (newval == oldval) break; int curval; if (is_recording()) { pthread_log_record (0, PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling, 1); curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, oldval); pthread_log_record (curval, PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling, 0); } else if (is_replaying()) { pthread_log_replay (PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling); curval = pthread_log_replay (PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling); } else { curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, oldval); } if (__builtin_expect (curval == oldval, 1)) { if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) { THREAD_SETMEM (self, result, PTHREAD_CANCELED); __do_cancel (); } break; } /* Prepare the next round. */ oldval = curval; } return oldval; }
void __cleanup_fct_attribute __pthread_register_cancel_defer (__pthread_unwind_buf_t *buf) { struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; struct pthread *self = THREAD_SELF; /* Store old info. */ ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); int cancelhandling; if (is_recording()) { pthread_log_record (0, PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling, 1); cancelhandling = THREAD_GETMEM (self, cancelhandling); pthread_log_record (cancelhandling, PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling, 0); } else if (is_replaying()) { pthread_log_replay (PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling); cancelhandling = pthread_log_replay (PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling); } else { cancelhandling = THREAD_GETMEM (self, cancelhandling); } /* Disable asynchronous cancellation for now. */ if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0)) while (1) { int curval; if (is_recording()) { pthread_log_record (0, PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling, 1); curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, cancelhandling & ~CANCELTYPE_BITMASK, cancelhandling); pthread_log_record (curval, PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling, 0); } else if (is_replaying()) { pthread_log_replay (PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling); curval = pthread_log_replay (PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling); } else { curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, cancelhandling & ~CANCELTYPE_BITMASK, cancelhandling); } if (__builtin_expect (curval == cancelhandling, 1)) /* Successfully replaced the value. */ break; /* Prepare for the next round. */ cancelhandling = curval; } ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED); /* Store the new cleanup handler info. */ THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); }
static ssize_t scribe_do_write(struct file *file, const char __user *buf, ssize_t count, loff_t *ppos) { struct scribe_ps *scribe = current->scribe; int force_block = 0; ssize_t ret; if (!is_scribed(scribe)) return do_write(file, buf, count, ppos, force_block); if (is_kernel_copy()) goto out; if (!should_scribe_data(scribe)) goto out; scribe_need_syscall_ret(scribe); if (is_replaying(scribe)) { count = scribe->orig_ret; if (count <= 0) return count; force_block = 1; } out: scribe->in_read_write = true; ret = do_write(file, buf, count, ppos, force_block); scribe->in_read_write = false; return ret; }
void __cleanup_fct_attribute __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf) { struct pthread *self = THREAD_SELF; struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev); int cancelhandling; if (is_recording()) { pthread_log_record (0, PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling, 1); cancelhandling = THREAD_GETMEM (self, cancelhandling); pthread_log_record (cancelhandling, PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling, 0); } else if (is_replaying()) { pthread_log_replay (PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling); cancelhandling = pthread_log_replay (PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling); } else { cancelhandling = THREAD_GETMEM (self, cancelhandling); } if (ibuf->priv.data.canceltype != PTHREAD_CANCEL_DEFERRED && (cancelhandling & CANCELTYPE_BITMASK) == 0) { while (1) { int curval; if (is_recording()) { pthread_log_record (0, PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling, 1); curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, cancelhandling | CANCELTYPE_BITMASK, cancelhandling); pthread_log_record (curval, PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling, 0); } else if (is_replaying()) { pthread_log_replay (PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling); curval = pthread_log_replay (PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling); } else { curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, cancelhandling | CANCELTYPE_BITMASK, cancelhandling); } if (__builtin_expect (curval == cancelhandling, 1)) /* Successfully replaced the value. */ break; /* Prepare for the next round. */ cancelhandling = curval; } CANCELLATION_P (self); } }
static int scribe_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len, int flags) { struct scribe_ps *scribe = current->scribe; int ret, err; if (scribe_is_deterministic(sock) || !is_scribed(scribe)) { if (is_replaying(scribe)) { flags &= ~MSG_DONTWAIT; flags |= MSG_WAITALL; if (!scribe_is_in_read_write(scribe)) total_len = scribe->orig_ret; if ((ssize_t)total_len <= 0) return total_len; } scribe_data_det(); ret = sock->real_ops->recvmsg(iocb, sock, m, total_len, flags), scribe_data_pop_flags(); return ret; } scribe_data_non_det_need_info(); err = scribe_result_cond( ret, sock->real_ops->recvmsg(iocb, sock, m, total_len, flags), !scribe_is_in_read_write(scribe) || ret > 0); if (err) goto out; if (ret <= 0) goto out; if (is_replaying(scribe)) scribe_emul_copy_to_user(scribe, NULL, INT_MAX); err = scribe_value(&m->msg_namelen); if (err) goto out; err = scribe_buffer(m->msg_name, m->msg_namelen); out: scribe_data_pop_flags(); return err ?: ret; }
static int scribe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { struct scribe_ps *scribe = current->scribe; int ret, err; if (scribe_is_deterministic(sock) || !is_scribed(scribe)) { if (is_replaying(scribe)) { m->msg_flags &= ~MSG_DONTWAIT; if (!scribe_is_in_read_write(scribe)) total_len = scribe->orig_ret; if ((ssize_t)total_len <= 0) return total_len; } ret = sock->real_ops->sendmsg(iocb, sock, m, total_len); return ret; } scribe_data_need_info(); err = scribe_result_cond( ret, sock->real_ops->sendmsg(iocb, sock, m, total_len), !scribe_is_in_read_write(scribe) || ret > 0); if (err) goto out; if (ret <= 0) goto out; if (is_replaying(scribe)) scribe_emul_copy_from_user(scribe, NULL, INT_MAX); out: scribe_data_pop_flags(); return err ?: ret; }
// REPLAY: The above function only modifies cancelhandling void internal_function attribute_hidden __pthread_disable_asynccancel (int oldtype) { if (is_recording()) { struct pthread *self = THREAD_SELF; pthread_log_record (0, PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling, 1); __internal_pthread_disable_asynccancel(oldtype); pthread_log_record (0, PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling, 0); } else if (is_replaying()) { struct pthread *self = THREAD_SELF; pthread_log_replay (PTHREAD_CANCELHANDLING_ENTER, (u_long) &self->cancelhandling); pthread_log_replay (PTHREAD_CANCELHANDLING_EXIT, (u_long) &self->cancelhandling); } else { __internal_pthread_disable_asynccancel(oldtype); } }
bool DetCheckTraceBuilder::cond_branch(bool cnd){ if(is_replaying()){ assert(cond_branch_log_index < cond_branch_log.size()); bool logged = cond_branch_log[cond_branch_log_index]; ++cond_branch_log_index; if(logged != cnd){ nondeterminism_error("Branch condition value changed in replay."); return false; } }else{ if(cond_branch_log_index < cond_branch_log.size()){ cond_branch_log[cond_branch_log_index] = cnd; }else{ assert(cond_branch_log_index == cond_branch_log.size()); cond_branch_log.push_back(cnd); } ++cond_branch_log_index; } return true; }
static ssize_t scribe_do_read(struct file *file, char __user *buf, ssize_t len, loff_t *ppos) { struct scribe_ps *scribe = current->scribe; int force_block = 0; ssize_t ret; if (!is_scribed(scribe)) return do_read(file, buf, len, ppos, force_block); if (is_kernel_copy()) goto out; if (!should_scribe_data(scribe)) goto out; scribe_need_syscall_ret(scribe); if (is_replaying(scribe)) { len = scribe->orig_ret; if (len <= 0) return len; force_block = 1; } if (is_deterministic(file)) goto out; scribe_data_non_det(); if (is_recording(scribe)) goto out; return scribe_emul_copy_to_user(scribe, buf, len); out: scribe->in_read_write = true; ret = do_read(file, buf, len, ppos, force_block); scribe->in_read_write = false; return ret; }
static int scribe_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { struct scribe_ps *scribe = current->scribe; int ret, err; scribe_data_non_det_need_info(); err = scribe_result( ret, sock->real_ops->getsockopt(sock, level, optname, optval, optlen)); if (err) return err; if (ret < 0) return ret; if (is_replaying(scribe)) scribe_emul_copy_to_user(scribe, NULL, INT_MAX); return ret; }
static ssize_t scribe_do_readv_writev(int type, struct file *file, const struct iovec __user * uvector, unsigned long nr_segs, loff_t *pos) { struct scribe_ps *scribe = current->scribe; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov = iovstack; int force_block = 0; ssize_t ret, len = 0; if (!is_scribed(scribe)) return do_readv_writev(type, file, uvector, nr_segs, 0, pos, force_block); if (is_kernel_copy()) goto out; if (!should_scribe_data(scribe)) goto out; scribe_need_syscall_ret(scribe); if (is_replaying(scribe)) { len = scribe->orig_ret; if (len <= 0) { rw_copy_check_uvector(type, uvector, nr_segs, ARRAY_SIZE(iovstack), iovstack, &iov); ret = len; goto free; } force_block = 1; } if (type == READ) { if (is_deterministic(file)) goto out; scribe_data_non_det(); if (is_recording(scribe)) goto out; rw_copy_check_uvector(type, uvector, nr_segs, ARRAY_SIZE(iovstack), iovstack, &iov); ret = __do_loop_readv_writev(file, iov, nr_segs, len, pos, io_scribe_emul_copy_to_user); goto free; } out: scribe->in_read_write = true; ret = do_readv_writev(type, file, uvector, nr_segs, len, pos, force_block); scribe->in_read_write = false; free: if (iov != iovstack) kfree(iov); return ret; }