Пример #1
0
void SCHEDULER_add_event(int64_t seq_time, SchedulerCallback callback, const union SuperType *args, int num_args, enum SchedulerPriority priority){
  R_ASSERT(PLAYER_current_thread_has_lock());
  
  // An event created by an RT_process function needs to run right away.
  // If not it won't be run until the next audio block since SCHEDULER_called_per_block
  // has already been called for this audio block.
  // (Q: why not do this for events genereated by the editor too?
  //  A: Because then effects could be run after notes, "note on" events could be run before "note off" events, and so forth)
  if (false==pc->is_treating_editor_events && seq_time < pc->end_time) {
    callback(seq_time, args);
    return;
  }
      
  int64_t time = seq_to_scheduler_time(seq_time);

  //args=NULL; // test crashreporter
  
#if 0
  printf("|||||||||| Adding event at seq_time %d, scheduler_time %d. g_current_time: %d, pc->start_time: %d\n",
         (int)seq_time,(int)time,
         (int)g_current_time,(int)pc->start_time);
#endif

  if(g_queue_size > QUEUE_SIZE-2){
    printf("SCHEDULER: queue full. Skipping.\n");
    return;
  }
  if(num_args>MAX_ARGS){
    printf("Max %d args allowed for scheduler...\n",MAX_ARGS);
    return;
  }
  
  // Add priority bit.
  time = time << SCHEDULER_NUM_PRIORITY_BITS;
  time = time + priority;

  event_t *event = get_free_event();
  event->callback=callback;
  event->time = time;

  g_queue_size++;

  int i = g_queue_size;
  int new_i = i >> 1;

  while(time <= g_queue[new_i]->time){ // '<=' (instead of '<') means that the event will be inserted after events with the same time.
    g_queue[i] = g_queue[new_i];
    i = new_i;
    new_i = new_i >> 1;
  }
  g_queue[i] = event;


  int argnum;
  for(argnum=0;argnum<num_args;argnum++)
    event->args[argnum] = args[argnum];
}
Пример #2
0
/*
 *	monitor_msg - thread routine to monitor messages.
 */
void *
monitor_msg(
	void *vlibrary)
{
	int 		exit_status = 0;
	sigset_t 	signal_set;
	library_t 	*library = (library_t *)vlibrary;
	robo_event_t 		*current_event;
	struct sigaction 	sig_action;
	message_request_t 	*message, shutdown;
	enum sam_mess_type 	mtype;

	/* dummy up a shutdown message */
	(void) memset(&shutdown, 0, sizeof (message_request_t));
	(void) memset(&sig_action, 0, sizeof (struct sigaction));

	shutdown.mtype = MESS_MT_SHUTDOWN;
	/* LINTED constant truncated by assignment */
	shutdown.message.magic = MESSAGE_MAGIC;
	shutdown.message.command = MESS_CMD_SHUTDOWN;

	/*
	 * Should have been called with all signals blocked,
	 * now let sigemt be delivered and just exit when it is
	 */
	sig_action.sa_handler = sig_catch;
	sig_action.sa_flags = 0;
	(void) sigemptyset(&signal_set);
	(void) sigaddset(&signal_set, SIGEMT);
	(void) sigaction(SIGEMT, &sig_action, (struct sigaction *)NULL);
	(void) thr_sigsetmask(SIG_UNBLOCK, &signal_set, NULL);

	mutex_lock(&library->mutex);	/* wait for initialize */
	mutex_unlock(&library->mutex);

	message = (message_request_t *)SHM_REF_ADDR(library->un->dt.rb.message);
	if (thr_create(NULL, MD_THR_STK, stk_acs_response, (void *)library,
	    (THR_BOUND | THR_NEW_LWP | THR_DETACHED), NULL)) {
		sam_syslog(LOG_CRIT,
		    "Unable to start stk_acs_response thread: %m.");
		thr_exit(NULL);
	}

	/* Main loop */
	for (;;) {
		current_event = get_free_event(library);

		/*
		 * Zeroing the struct has the effect of initializing
		 * the mutex and the condition to USYNC_THREAD, just
		 * what we want
		 */
		(void) memset(current_event, 0, sizeof (robo_event_t));
		current_event->status.bits = REST_FREEMEM;

		/* Wait for a message */
		mutex_lock(&message->mutex);
		while (message->mtype == MESS_MT_VOID)
			cond_wait(&message->cond_r, &message->mutex);

		/* Copy the request into the event */
		current_event->request.message = message->message;
		mtype = message->mtype;	/* capture message type */

		message->mtype = MESS_MT_VOID;	/* release the message area */
		message->message.exit_id.pid = 0;
		cond_signal(&message->cond_i);	/* and wake up anyone waiting */
		mutex_unlock(&message->mutex);

		if (mtype == MESS_MT_APIHELP) {
			current_event->next = NULL;
			mutex_lock(&stk_acs_mutex);
			/*
			 * If the list is NULL, this will be the only
			 * entry on the list.  Set the head and last to current
			 */
			if (stk_acs_event_head == NULL) {
				stk_acs_event_head =
				    stk_acs_event_last = current_event;
				cond_signal(&stk_acs_cond);
			} else {
				/*
				 * If the head is not null, last points to the
				 * last entry on the list. Point last
				 * next to the current then set last = current
				 */
				stk_acs_event_last->next = current_event;
				stk_acs_event_last = current_event;
			}

			mutex_unlock(&stk_acs_mutex);
		} else {
			current_event->type = EVENT_TYPE_MESS;

			/*
			 * Put the event on the list and
			 * wake up the event handler
			 */
			add_to_end(library, current_event);
			if (message->mtype == MESS_MT_SHUTDOWN) {
				if (DBG_LVL(SAM_DBG_DEBUG))
					sam_syslog(LOG_DEBUG,
					"shutdown request:%s:%d.",
					    __FILE__, __LINE__);
				threads[STK_MSG_THREAD] = (thread_t)-1;
				thr_exit(&exit_status);
				/* NOTREACHED */
				return (NULL);
			}
		}
	}
}