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; } }
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); }
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); }
/** * 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; }
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; }
/** * 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); }
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 } }
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, ¶m) == -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 } }
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; } }
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, ¶m) == -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); }