示例#1
0
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;
}
示例#2
0
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);
}
示例#3
0
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);
    }
}
示例#4
0
文件: video.cpp 项目: kaspal/mame
void video_manager::toggle_record_movie()
{
	if (!is_recording())
	{
		begin_recording(nullptr, MF_MNG);
		machine().popmessage("REC START");
	}
	else
	{
		end_recording(MF_MNG);
		machine().popmessage("REC STOP");
	}
}
示例#5
0
文件: video.cpp 项目: MASHinfo/mame
void video_manager::toggle_record_movie(movie_format format)
{
	if (!is_recording())
	{
		begin_recording(nullptr, format);
		machine().popmessage("REC START (%s)", format == MF_MNG ? "MNG" : "AVI");
	}
	else
	{
		end_recording(format);
		machine().popmessage("REC STOP (%s)", format == MF_MNG ? "MNG" : "AVI");
	}
}
示例#6
0
// 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);
  }
}
示例#7
0
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;
}
示例#8
0
static int get_data_event(struct scribe_ps *scribe, struct data_desc *desc)
{
	union scribe_event_data_union event;

	if (is_recording(scribe)) {
		event = scribe->prepared_data_event;
		if (event.generic) {
			scribe->prepared_data_event.generic = NULL;

			if (desc->do_info) {
				/* we're good */
			} else if (desc->do_extra) {
				BUG_ON(event.extra->h.size < desc->size);
				event.extra->h.size = desc->size;
			} else {
				BUG_ON(event.regular->h.size < desc->size);
				event.regular->h.size = desc->size;
			}
			goto out;
		}

		if (desc->do_info)
			event.info = scribe_alloc_event(
					SCRIBE_EVENT_DATA_INFO);
		else if (desc->do_extra)
			event.extra = scribe_alloc_event_sized(
					SCRIBE_EVENT_DATA_EXTRA, desc->size);
		else
			event.regular = scribe_alloc_event_sized(
					SCRIBE_EVENT_DATA, desc->size);
		if (!event.generic) {
			scribe_kill(scribe->ctx, -ENOMEM);
			return -ENOMEM;
		}
		goto out;
	} else /* replaying */ {
		event = scribe->prepared_data_event;
		if (event.generic) {
			scribe->prepared_data_event.generic = NULL;
			goto out;
		}

		/*
		 * Not using scribe_dequeue_event_sized() because we don't
		 * really know the size (maybe we are in
		 * scribe_prepare_data_event() and @desc->size would only be the
		 * maximum size).
		 */

		/*
		 * XXX XXX We cannot dequeue in the middle of the stream
		 * because our data event may act as a fence.
		 * So we'll peek, which means that we'll have to dequeue it
		 * eventually.
		 */

		if (desc->do_info)
			event.generic = scribe_find_event_specific(
					scribe, SCRIBE_EVENT_DATA_INFO);
		else if (desc->do_extra)
			event.generic = scribe_find_event_specific(
					scribe, SCRIBE_EVENT_DATA_EXTRA);
		else
			event.generic = scribe_find_event_specific(
					scribe, SCRIBE_EVENT_DATA);
		if (IS_ERR(event.generic))
			return PTR_ERR(event.generic);
	}
out:
	desc->event = event;
	return 0;
}
示例#9
0
文件: video.cpp 项目: MASHinfo/mame
void video_manager::record_frame()
{
	// ignore if nothing to do
	if (!is_recording())
		return;

	// start the profiler and get the current time
	g_profiler.start(PROFILER_MOVIE_REC);
	attotime curtime = machine().time();

	screen_device_iterator device_iterator = screen_device_iterator(machine().root_device());
	screen_device_iterator::auto_iterator iter = device_iterator.begin();

	for (uint32_t index = 0; index < (std::max)(m_mngs.size(), m_avis.size()); index++, iter++)
	{
		// create the bitmap
		create_snapshot_bitmap(iter.current());

		// handle an AVI recording
		if ((index < m_avis.size()) && m_avis[index].m_avi_file)
		{
			avi_info_t &avi_info = m_avis[index];

			// loop until we hit the right time
			while (avi_info.m_avi_next_frame_time <= curtime)
			{
				// write the next frame
				avi_file::error avierr = avi_info.m_avi_file->append_video_frame(m_snap_bitmap);
				if (avierr != avi_file::error::NONE)
				{
					g_profiler.stop(); // FIXME: double exit if this happens?
					end_recording_avi(index);
					break;
				}

				// advance time
				avi_info.m_avi_next_frame_time += avi_info.m_avi_frame_period;
				avi_info.m_avi_frame++;
			}
		}

		// handle a MNG recording
		if ((index < m_mngs.size()) && m_mngs[index].m_mng_file)
		{
			mng_info_t &mng_info = m_mngs[index];

			// loop until we hit the right time
			while (mng_info.m_mng_next_frame_time <= curtime)
			{
				// set up the text fields in the movie info
				png_info pnginfo;
				if (mng_info.m_mng_frame == 0)
				{
					std::string text1 = std::string(emulator_info::get_appname()).append(" ").append(emulator_info::get_build_version());
					std::string text2 = std::string(machine().system().manufacturer).append(" ").append(machine().system().type.fullname());
					pnginfo.add_text("Software", text1.c_str());
					pnginfo.add_text("System", text2.c_str());
				}

				// write the next frame
				screen_device *screen = iter.current();
				const rgb_t *palette = (screen != nullptr && screen->has_palette()) ? screen->palette().palette()->entry_list_adjusted() : nullptr;
				int entries = (screen != nullptr && screen->has_palette()) ? screen->palette().entries() : 0;
				png_error error = mng_capture_frame(*mng_info.m_mng_file, pnginfo, m_snap_bitmap, entries, palette);
				if (error != PNGERR_NONE)
				{
					g_profiler.stop(); // FIXME: double exit if this happens?
					end_recording_mng(index);
					break;
				}

				// advance time
				mng_info.m_mng_next_frame_time += mng_info.m_mng_frame_period;
				mng_info.m_mng_frame++;
			}
		}

		if (!m_snap_native)
		{
			break;
		}
	}

	g_profiler.stop();
}
示例#10
0
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;
}