void
ags_soundcard_thread_dispatch_callback(AgsPollFd *poll_fd,
				       AgsSoundcardThread *soundcard_thread)
{
  AgsAudioLoop *audio_loop;

  AgsPollingThread *polling_thread;
  
  guint time_spent;

  audio_loop = (AgsAudioLoop *) ags_thread_get_toplevel((AgsThread *) soundcard_thread);

  if(ags_soundcard_is_available(AGS_SOUNDCARD(soundcard_thread->soundcard))){
    pthread_mutex_lock(audio_loop->timing_mutex);

    g_atomic_int_set(&(audio_loop->time_spent),
		     audio_loop->time_cycle);

    pthread_mutex_unlock(audio_loop->timing_mutex);

    //    ags_main_loop_interrupt(AGS_MAIN_LOOP(audio_loop),
    //			    AGS_THREAD_SUSPEND_SIG,
    //			    0, &time_spent);

    polling_thread = (AgsPollingThread *) ags_thread_find_type((AgsThread *) audio_loop,
							       AGS_TYPE_POLLING_THREAD);

    if(polling_thread != NULL){
      g_atomic_int_or(&(polling_thread->flags),
		      AGS_POLLING_THREAD_OMIT);
      g_atomic_int_inc(&(polling_thread->omit_count));
    }
  }
}
void
ags_soundcard_thread_init(AgsSoundcardThread *soundcard_thread)
{
  AgsThread *thread;

  AgsConfig *config;
  
  guint samplerate;
  guint buffer_size;
  
  thread = (AgsThread *) soundcard_thread;

  g_atomic_int_or(&(thread->flags),
		  (AGS_THREAD_START_SYNCED_FREQ |
		   AGS_THREAD_INTERMEDIATE_POST_SYNC));  
  
  //  g_atomic_int_or(&(thread->flags),
  //		  AGS_THREAD_TIMING);

  config = ags_config_get_instance();
  
  samplerate = (guint) ags_soundcard_helper_config_get_samplerate(config);
  buffer_size = (guint) ags_soundcard_helper_config_get_buffer_size(config);

  thread->freq = ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;

  /*  */
  soundcard_thread->soundcard_capability = 0;

  soundcard_thread->soundcard = NULL;
  soundcard_thread->error = NULL;
}
void
ags_soundcard_thread_stop(AgsThread *thread)
{
  AgsSoundcardThread *soundcard_thread;

  AgsThread *main_loop;
  AgsPollingThread *polling_thread;
  
  GObject *soundcard;

  GList *poll_fd;
    
  soundcard_thread = AGS_SOUNDCARD_THREAD(thread);
  main_loop = ags_thread_get_toplevel(thread);

  soundcard = soundcard_thread->soundcard;

  /* stop thread and soundcard */
  AGS_THREAD_CLASS(ags_soundcard_thread_parent_class)->stop(thread);

  //FIXME:JK: is this safe?
  ags_soundcard_stop(AGS_SOUNDCARD(soundcard));

  g_atomic_int_or(&(thread->flags),
		  AGS_THREAD_TIMING);

  /* find polling thread */
  polling_thread = (AgsPollingThread *) ags_thread_find_type(main_loop,
							     AGS_TYPE_POLLING_THREAD);
    
  /* remove poll fd */
  poll_fd = ags_soundcard_get_poll_fd(AGS_SOUNDCARD(soundcard));
    
  while(poll_fd != NULL){
    if(polling_thread != NULL){
      gint position;
      
      g_object_disconnect(G_OBJECT(poll_fd->data),
			  "any_signal::dispatch",
			  G_CALLBACK(ags_soundcard_thread_dispatch_callback),
			  soundcard_thread,
			  NULL);
      
      ags_polling_thread_remove_poll_fd(polling_thread,
					poll_fd->data);
    }
    
    poll_fd = poll_fd->next;
  }
}
Esempio n. 4
0
guint
ags_polling_thread_interrupted(AgsThread *thread,
			       int sig,
			       guint time_cycle, guint *time_spent)
{
  AgsPollingThread *polling_thread;

  polling_thread = (AgsPollingThread *) thread;
  
  if((AGS_THREAD_INTERRUPTED & (g_atomic_int_get(&(thread->sync_flags)))) == 0){
    g_atomic_int_or(&(polling_thread->flags),
		    AGS_POLLING_THREAD_OMIT);
  }

  return(0);
}
Esempio n. 5
0
void
ags_thread_suspend_handler(int sig)
{
#ifdef AGS_DEBUG
  g_message("thread suspend\0");
#endif

  if(ags_thread_self == NULL)
    return;

  if ((AGS_THREAD_SUSPENDED & (g_atomic_int_get(&(ags_thread_self->flags)))) != 0) return;

  g_atomic_int_or(&(ags_thread_self->flags),
		  AGS_THREAD_SUSPENDED);

  ags_thread_suspend(ags_thread_self);

  do sigsuspend(&(ags_thread_self->wait_mask)); while ((AGS_THREAD_SUSPENDED & (g_atomic_int_get(&(ags_thread_self->flags)))) != 0);
}
Esempio n. 6
0
/**
 * bd_s390_check_deps:
 *
 * Returns: whether the plugin's runtime dependencies are satisfied or not
 *
 * Function checking plugin's runtime dependencies.
 *
 */
gboolean bd_s390_check_deps () {
    GError *error = NULL;
    guint i = 0;
    gboolean status = FALSE;
    gboolean ret = TRUE;

    for (i=0; i < DEPS_LAST; i++) {
        status = bd_utils_check_util_version (deps[i].name, deps[i].version,
                                              deps[i].ver_arg, deps[i].ver_regexp, &error);
        if (!status)
            g_warning ("%s", error->message);
        else
            g_atomic_int_or (&avail_deps, 1 << i);
        g_clear_error (&error);
        ret = ret && status;
    }

    if (!ret)
        g_warning("Cannot load the s390 plugin");

    return ret;
}
Esempio n. 7
0
void
ags_polling_thread_init(AgsPollingThread *polling_thread)
{
  AgsThread *thread;

  thread = (AgsThread *) polling_thread;
  g_atomic_int_or(&(thread->sync_flags),
		  (AGS_THREAD_RESUME_INTERRUPTED));

  thread->freq = AGS_POLLING_THREAD_DEFAULT_JIFFIE;
  
  g_atomic_int_set(&(polling_thread->flags),
		   0);

  g_atomic_int_set(&(polling_thread->omit_count),
		   0);

  /* fd mutex */
  polling_thread->fd_mutexattr = (pthread_mutexattr_t *) malloc(sizeof(pthread_mutexattr_t));
    
  pthread_mutexattr_init(polling_thread->fd_mutexattr);
  pthread_mutexattr_settype(polling_thread->fd_mutexattr,
			    PTHREAD_MUTEX_RECURSIVE);

#ifdef __linux__
  pthread_mutexattr_setprotocol(polling_thread->fd_mutexattr,
				PTHREAD_PRIO_INHERIT);
#endif

  polling_thread->fd_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
  pthread_mutex_init(polling_thread->fd_mutex,
		     polling_thread->fd_mutexattr);
  
  polling_thread->fds = NULL;

  polling_thread->poll_fd = NULL;
}
static gboolean
gum_memory_access_monitor_on_exception (GumExceptionDetails * details,
                                        gpointer user_data)
{
  GumMemoryAccessMonitor * self = GUM_MEMORY_ACCESS_MONITOR_CAST (user_data);
  const GumMemoryAccessMonitorPrivate * priv = self->priv;
  GumMemoryAccessDetails d;
  guint i;

  d.operation = details->memory.operation;
  d.from = details->address;
  d.address = details->memory.address;

  for (i = 0; i != priv->num_pages; i++)
  {
    const GumPageDetails * page = &priv->pages_details[i];
    const GumMemoryRange * r = &priv->ranges[page->range_index];
    guint operation_mask;
    guint operations_reported;
    guint pages_remaining;

    if ((page->address <= d.address) && 
        ((guint8 *) page->address + priv->page_size > (guint8*) d.address))
    {
      /* make sure that we don't misinterpret access violation / page guard */
      if (page->is_guarded)
      {
        if (details->type != GUM_EXCEPTION_GUARD_PAGE)
          return FALSE;
      }
      else if (details->type == GUM_EXCEPTION_ACCESS_VIOLATION)
      {
        GumPageProtection gum_original_protection = 
            gum_page_protection_from_windows (page->original_protection);
        switch (d.operation)
        {
        case GUM_MEMOP_READ:
          if ((gum_original_protection & GUM_PAGE_READ) == 0)
            return FALSE;
          break;
        case GUM_MEMOP_WRITE:
          if ((gum_original_protection & GUM_PAGE_WRITE) == 0)
            return FALSE;
          break;
        case GUM_MEMOP_EXECUTE:
          if ((gum_original_protection & GUM_PAGE_EXECUTE) == 0)
            return FALSE;
          break;
        default:
          g_assert_not_reached();
        }
      }
      else 
        return FALSE;

      /* restore the original protection if needed */
      if (priv->auto_reset && !page->is_guarded)
      {
        DWORD old_prot;
        /* may be called multiple times in case of simultaneous access
         * but it should not be a problem */
        VirtualProtect (
            (guint8 *) d.address - (((guintptr) d.address) % priv->page_size),
            priv->page_size, page->original_protection, &old_prot);
      }

      /* if an operation was already reported, don't report it. */
      operation_mask = 1 << d.operation;
      operations_reported = g_atomic_int_or (&page->completed, operation_mask);
      if ((operations_reported != 0) && priv->auto_reset)
        return FALSE;

      pages_remaining;
      if (!operations_reported)
        pages_remaining = g_atomic_int_add (&priv->pages_remaining, -1) - 1;
      else
        pages_remaining = g_atomic_int_get (&priv->pages_remaining);
      d.pages_completed = priv->pages_total - pages_remaining;

      d.range_index = page->range_index;
      d.page_index = (guint8 *) d.address - (guint8 *) r->base_address;
      d.page_index = d.page_index / priv->page_size;
      d.pages_total = priv->pages_total;

      priv->notify_func (self, &d, priv->notify_data);

      return TRUE;
    }
  }

  return FALSE;
}
Esempio n. 9
0
/**
 * g_atomic_int_or:
 * @atomic: a pointer to a #gint or #guint
 * @val: the value to 'or'
 *
 * Performs an atomic bitwise 'or' of the value of @atomic and @val,
 * storing the result back in @atomic.
 *
 * Think of this operation as an atomic version of
 * <literal>{ tmp = *atomic; *@atomic |= @val; return tmp; }</literal>
 *
 * This call acts as a full compiler and hardware memory barrier.
 *
 * Returns: the value of @atomic before the operation, unsigned
 *
 * Since: 2.30
 **/
guint
(g_atomic_int_or) (volatile guint *atomic,
                   guint           val)
{
  return g_atomic_int_or (atomic, val);
}
Esempio n. 10
0
void*
ags_thread_pool_creation_thread(void *ptr)
{
  AgsThreadPool *thread_pool;
  AgsThread *thread;
  GList *tmplist;
  guint n_threads, max_threads;
  guint i, i_stop;
  
  thread_pool = AGS_THREAD_POOL(ptr);
  
#ifdef AGS_DEBUG
  g_message("ags_thread_pool_creation_thread\0");
#endif
  
  while((AGS_THREAD_POOL_RUNNING & (g_atomic_int_get(&(thread_pool->flags)))) != 0){
#ifdef AGS_DEBUG
    g_message("ags_thread_pool_creation_thread@loopStart\0");
#endif
    
    pthread_mutex_lock(thread_pool->creation_mutex);
    
    g_atomic_int_or(&(thread_pool->flags),
		    AGS_THREAD_POOL_READY);
    
    while(g_atomic_int_get(&(thread_pool->newly_pulled)) == 0){
      pthread_cond_wait(thread_pool->creation_cond,
			thread_pool->creation_mutex);
    }

    n_threads = g_atomic_int_get(&(thread_pool->n_threads));
    max_threads = g_atomic_int_get(&(thread_pool->max_threads));

    i_stop = g_atomic_int_get(&(thread_pool->newly_pulled));
    g_atomic_int_set(&(thread_pool->newly_pulled),
		     0);
    
#ifdef AGS_DEBUG
    g_message("ags_thread_pool_creation_thread@loop0\0");
#endif
    
    g_atomic_int_and(&(thread_pool->flags),
		     (~AGS_THREAD_POOL_READY));
    
    if(n_threads < max_threads){
      for(i = 0; i < i_stop && n_threads < max_threads; i++){
	thread = (AgsThread *) ags_returnable_thread_new(thread_pool);
	tmplist = g_atomic_pointer_get(&(thread_pool->returnable_thread));
	g_atomic_pointer_set(&(thread_pool->returnable_thread),
			     g_list_prepend(tmplist, thread));      
	ags_thread_add_child(AGS_THREAD(thread_pool->parent),
			     thread);
	ags_connectable_connect(AGS_CONNECTABLE(thread));
	g_atomic_int_inc(&(thread_pool->n_threads));

	n_threads++;
      }
    }

    pthread_mutex_unlock(thread_pool->creation_mutex);
    
#ifdef AGS_DEBUG
    g_message("ags_thread_pool_creation_thread@loopEND\0");
#endif
  }
}
Esempio n. 11
0
void
ags_soundcard_thread_run(AgsThread *thread)
{
  AgsSoundcardThread *soundcard_thread;

  GObject *soundcard;

  GList *poll_fd;
  
  gboolean is_playing, is_recording;
  
  GError *error;

  soundcard_thread = AGS_SOUNDCARD_THREAD(thread);

  soundcard = soundcard_thread->soundcard;

  /* real-time setup */
#ifdef AGS_WITH_RT
  if((AGS_THREAD_RT_SETUP & (g_atomic_int_get(&(thread->flags)))) == 0){
    struct sched_param param;
    
    /* Declare ourself as a real time task */
    param.sched_priority = AGS_RT_PRIORITY;
      
    if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
      perror("sched_setscheduler failed");
    }

    g_atomic_int_or(&(thread->flags),
		    AGS_THREAD_RT_SETUP);
  }
#endif

  /* playback */
  if((AGS_SOUNDCARD_CAPABILITY_PLAYBACK & (soundcard_thread->soundcard_capability)) != 0){
    is_playing = ags_soundcard_is_playing(AGS_SOUNDCARD(soundcard));
  
    if(is_playing){
      error = NULL;
      ags_soundcard_play(AGS_SOUNDCARD(soundcard),
			 &error);

      if(error != NULL){
	//TODO:JK: implement me

	g_warning("%s",
		  error->message);
      }
    }
  }

  /* capture */
  if((AGS_SOUNDCARD_CAPABILITY_CAPTURE & (soundcard_thread->soundcard_capability)) != 0){
    is_recording = ags_soundcard_is_recording(AGS_SOUNDCARD(soundcard));
  
    if(is_recording){
      error = NULL;
      ags_soundcard_record(AGS_SOUNDCARD(soundcard),
			   &error);

      if(error != NULL){
	//TODO:JK: implement me

	g_warning("%s",
		  error->message);
      }
    }
  }

  /* duplex */
  if((AGS_SOUNDCARD_CAPABILITY_DUPLEX & (soundcard_thread->soundcard_capability)) != 0){
    //TODO:JK: implement me
  }
}
Esempio n. 12
0
void
ags_soundcard_thread_set_property(GObject *gobject,
				  guint prop_id,
				  const GValue *value,
				  GParamSpec *param_spec)
{
  AgsSoundcardThread *soundcard_thread;

  soundcard_thread = AGS_SOUNDCARD_THREAD(gobject);

  switch(prop_id){
  case PROP_SOUNDCARD:
    {
      GObject *soundcard;

      guint samplerate;
      guint buffer_size;

      soundcard = (GObject *) g_value_get_object(value);

      if(soundcard_thread->soundcard != NULL){
	g_object_unref(G_OBJECT(soundcard_thread->soundcard));
      }

      if(soundcard != NULL){
	g_object_ref(G_OBJECT(soundcard));

	ags_soundcard_get_presets(AGS_SOUNDCARD(soundcard),
				  NULL,
				  &samplerate,
				  &buffer_size,
				  NULL);
	
	g_object_set(soundcard_thread,
		     "frequency", ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK,
		     NULL);

	/* playback */
	if(AGS_IS_DEVOUT(soundcard)){
	  g_atomic_int_or(&(AGS_THREAD(soundcard_thread)->flags),
			  (AGS_THREAD_INTERMEDIATE_POST_SYNC));
	}else if(AGS_IS_JACK_DEVOUT(soundcard) ||
		 AGS_IS_PULSE_DEVOUT(soundcard)){
	  g_atomic_int_or(&(AGS_THREAD(soundcard_thread)->flags),
			  (AGS_THREAD_INTERMEDIATE_POST_SYNC));
	}else if(AGS_IS_CORE_AUDIO_DEVOUT(soundcard)){
	  g_atomic_int_or(&(AGS_THREAD(soundcard_thread)->flags),
	  		  (AGS_THREAD_INTERMEDIATE_POST_SYNC));
	}

	/* capture */
	if(AGS_IS_DEVIN(soundcard)){
	  g_atomic_int_or(&(AGS_THREAD(soundcard_thread)->flags),
			  (AGS_THREAD_INTERMEDIATE_PRE_SYNC));
	}else if(AGS_IS_JACK_DEVIN(soundcard) ||
		 AGS_IS_PULSE_DEVIN(soundcard)){
	  g_atomic_int_or(&(AGS_THREAD(soundcard_thread)->flags),
			  (AGS_THREAD_INTERMEDIATE_PRE_SYNC));
	}else if(AGS_IS_CORE_AUDIO_DEVIN(soundcard)){
	  g_atomic_int_or(&(AGS_THREAD(soundcard_thread)->flags),
	  		  (AGS_THREAD_INTERMEDIATE_PRE_SYNC));
	}

	/* duplex */
	//TODO:JK: implement me
      }

      soundcard_thread->soundcard = G_OBJECT(soundcard);
    }
    break;
  case PROP_SOUNDCARD_CAPABILITY:
    {
      soundcard_thread->soundcard_capability = g_value_get_uint(value);
    }
    break;
  default:
    G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
    break;
  }
}
Esempio n. 13
0
void
ags_polling_thread_run(AgsThread *thread)
{
  AgsPollingThread *polling_thread;
  AgsThread *main_loop;
  
  GList *list;
  
  struct timespec timeout;

  sigset_t sigmask;
  gint position;
  int ret;

  polling_thread = AGS_POLLING_THREAD(thread);
  main_loop = ags_thread_get_toplevel(thread);
  
  /* real-time setup */
#ifdef AGS_WITH_RT
  if((AGS_THREAD_RT_SETUP & (g_atomic_int_get(&(thread->flags)))) == 0){
    struct sched_param param;
    
    /* Declare ourself as a real time task */
    param.sched_priority = AGS_POLLING_THREAD_RT_PRIORITY;
      
    if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
      perror("sched_setscheduler failed");
    }

    g_atomic_int_or(&(thread->flags),
		    AGS_THREAD_RT_SETUP);
  }
#endif

  sigemptyset(&sigmask);

  timeout.tv_sec = 0;

  if(g_atomic_int_get(&(main_loop->time_late)) != 0){
    timeout.tv_nsec = 0;
  }else{
    if(main_loop->tic_delay == main_loop->delay){
      if(AGS_THREAD_TOLERANCE > 0.0){
	timeout.tv_nsec = 0;
      }else{
	timeout.tv_nsec = -1 * AGS_THREAD_TOLERANCE;
      }
    }else{
      if(thread->freq > AGS_THREAD_HERTZ_JIFFIE){
	timeout.tv_nsec = (NSEC_PER_SEC / thread->freq + AGS_POLLING_THREAD_UNDERLOAD);
      }else{
	timeout.tv_nsec = (NSEC_PER_SEC / AGS_THREAD_HERTZ_JIFFIE + AGS_POLLING_THREAD_UNDERLOAD);
      }
    }
  }
  
  pthread_mutex_lock(polling_thread->fd_mutex);

  if((AGS_POLLING_THREAD_OMIT & (g_atomic_int_get(&(polling_thread->flags)))) == 0){
    list = polling_thread->poll_fd;

    /* pre flag */
    while(list != NULL){
      position = ags_polling_thread_fd_position(polling_thread,
						AGS_POLL_FD(list->data)->fd);

      if(position != -1 &&
	 AGS_POLL_FD(list->data)->poll_fd != NULL){
	AGS_POLL_FD(list->data)->poll_fd->events = polling_thread->fds[position].events;
      }

      list = list->next;
    }  

    /* poll */	
    if(polling_thread->fds != NULL){
#ifndef __APPLE__
      ppoll(polling_thread->fds,
	    g_list_length(polling_thread->poll_fd),
	    &timeout,
	    &sigmask);
#else
      poll(polling_thread->fds,
	   g_list_length(polling_thread->poll_fd),
	   timeout.tv_nsec / 1000);
#endif
    }

    /* post flag */
    list = polling_thread->poll_fd;

    while(list != NULL){
      if(AGS_POLL_FD(list->data)->delay_counter >= AGS_POLL_FD(list->data)->delay){
	position = ags_polling_thread_fd_position(polling_thread,
						  AGS_POLL_FD(list->data)->fd);

	if(position != -1){
	  if((POLLIN & (polling_thread->fds[position].revents)) != 0){
	    AGS_POLL_FD(list->data)->flags |= AGS_POLL_FD_INPUT;
	  }

	  if((POLLPRI & (polling_thread->fds[position].revents)) != 0){
	    AGS_POLL_FD(list->data)->flags |= AGS_POLL_FD_PRIORITY_INPUT;
	  }

	  if((POLLOUT & (polling_thread->fds[position].revents)) != 0){
	    AGS_POLL_FD(list->data)->flags |= AGS_POLL_FD_OUTPUT;
	  }

	  if((POLLHUP & (polling_thread->fds[position].revents)) != 0){
	    AGS_POLL_FD(list->data)->flags |= AGS_POLL_FD_HANG_UP;
	  }

	  /* do legacy */
	  if(AGS_POLL_FD(list->data)->poll_fd != NULL){
	    AGS_POLL_FD(list->data)->poll_fd->revents = polling_thread->fds[position].revents;
	  }

	  ags_poll_fd_dispatch(list->data);
      
	  AGS_POLL_FD(list->data)->flags &= (~(AGS_POLL_FD_INPUT |
					       AGS_POLL_FD_PRIORITY_INPUT |   
					       AGS_POLL_FD_OUTPUT |
					       AGS_POLL_FD_HANG_UP));
	  
	  AGS_POLL_FD(list->data)->delay_counter = 0.0;
	}else{
	  AGS_POLL_FD(list->data)->delay_counter += 1.0;
	}
      }
      
      list = list->next;
    }  
  }
  
  pthread_mutex_unlock(polling_thread->fd_mutex);
}