void _gsl_tick_stamp_set_leap (guint ticks) { GSL_SPIN_LOCK (&global_tick_stamp_mutex); global_tick_stamp_leaps = ticks; GSL_SPIN_UNLOCK (&global_tick_stamp_mutex); }
GslDataCache* gsl_data_cache_new (GslDataHandle *dhandle, guint padding) { guint node_size = CONFIG_NODE_SIZE () / sizeof (GslDataType); GslDataCache *dcache; g_return_val_if_fail (dhandle != NULL, NULL); g_return_val_if_fail (padding > 0, NULL); g_return_val_if_fail (dhandle->name != NULL, NULL); g_assert (node_size == sfi_alloc_upper_power2 (node_size)); g_return_val_if_fail (padding < node_size / 2, NULL); /* allocate new closed dcache if necessary */ dcache = sfi_new_struct (GslDataCache, 1); dcache->dhandle = gsl_data_handle_ref (dhandle); dcache->open_count = 0; sfi_mutex_init (&dcache->mutex); dcache->ref_count = 1; dcache->node_size = node_size; dcache->padding = padding; dcache->max_age = 0; dcache->high_persistency = FALSE; dcache->n_nodes = 0; dcache->nodes = g_renew (GslDataCacheNode*, NULL, UPPER_POWER2 (dcache->n_nodes)); GSL_SPIN_LOCK (&global_dcache_mutex); global_dcache_list = sfi_ring_append (global_dcache_list, dcache); global_dcache_count++; GSL_SPIN_UNLOCK (&global_dcache_mutex); return dcache; }
void gsl_data_cache_open (GslDataCache *dcache) { g_return_if_fail (dcache != NULL); g_return_if_fail (dcache->ref_count > 0); GSL_SPIN_LOCK (&dcache->mutex); if (!dcache->open_count) { BseErrorType error; error = gsl_data_handle_open (dcache->dhandle); if (error) { /* FIXME: this is pretty fatal, throw out zero blocks now? */ sfi_diag ("%s: failed to open \"%s\": %s", G_STRLOC, dcache->dhandle->name, bse_error_blurb (error)); } else { dcache->high_persistency = gsl_data_handle_needs_cache (dcache->dhandle); dcache->open_count = 1; dcache->ref_count++; } } else dcache->open_count++; GSL_SPIN_UNLOCK (&dcache->mutex); }
/** * @return GSL's execution tick stamp as unsigned 64bit integer * * Retrieve the global GSL tick counter stamp. * GSL increments its global tick stamp at certain intervals, * by specific amounts (refer to bse_engine_init() for further * details). The tick stamp is a non-wrapping, unsigned 64bit * integer greater than 0. Threads can schedule sleep interruptions * at certain tick stamps with sfi_thread_awake_after() and * sfi_thread_awake_before(). Tick stamp updating occours at * GSL engine block processing boundaries, so code that can * guarantee to not run across those boundaries (for instance * BseProcessFunc() functions) may use the macro GSL_TICK_STAMP * to retrieve the current tick in a faster manner (not involving * mutex locking). See also bse_module_tick_stamp(). * This function is MT-safe and may be called from any thread. */ guint64 gsl_tick_stamp (void) { guint64 stamp; GSL_SPIN_LOCK (&global_tick_stamp_mutex); stamp = bse_engine_exvar_tick_stamp; GSL_SPIN_UNLOCK (&global_tick_stamp_mutex); return stamp; }
/** * @return Current tick stamp and system time in micro seconds * * Get the system time of the last GSL global tick stamp update. * This function is MT-safe and may be called from any thread. */ GslTickStampUpdate gsl_tick_stamp_last (void) { GslTickStampUpdate ustamp; GSL_SPIN_LOCK (&global_tick_stamp_mutex); ustamp.tick_stamp = bse_engine_exvar_tick_stamp; ustamp.system_time = tick_stamp_system_time; GSL_SPIN_UNLOCK (&global_tick_stamp_mutex); return ustamp; }
GslDataHandle* gsl_data_handle_ref (GslDataHandle *dhandle) { g_return_val_if_fail (dhandle != NULL, NULL); g_return_val_if_fail (dhandle->ref_count > 0, NULL); GSL_SPIN_LOCK (&dhandle->mutex); dhandle->ref_count++; GSL_SPIN_UNLOCK (&dhandle->mutex); return dhandle; }
GslDataCache* gsl_data_cache_ref (GslDataCache *dcache) { g_return_val_if_fail (dcache != NULL, NULL); g_return_val_if_fail (dcache->ref_count > 0, NULL); /* we might get invoked with global_dcache_mutex locked */ GSL_SPIN_LOCK (&dcache->mutex); dcache->ref_count++; GSL_SPIN_UNLOCK (&dcache->mutex); return dcache; }
guint gsl_data_handle_bit_depth (GslDataHandle *dhandle) { guint n; g_return_val_if_fail (dhandle != NULL, 0); g_return_val_if_fail (dhandle->open_count > 0, 0); GSL_SPIN_LOCK (&dhandle->mutex); n = dhandle->open_count ? dhandle->setup.bit_depth : 0; GSL_SPIN_UNLOCK (&dhandle->mutex); return n; }
GslLong gsl_data_handle_length (GslDataHandle *dhandle) { GslLong l; g_return_val_if_fail (dhandle != NULL, 0); g_return_val_if_fail (dhandle->open_count > 0, 0); GSL_SPIN_LOCK (&dhandle->mutex); l = dhandle->open_count ? dhandle->setup.n_values : 0; GSL_SPIN_UNLOCK (&dhandle->mutex); return l; }
GslErrorType gsl_data_handle_open (GslDataHandle *dhandle) { g_return_val_if_fail (dhandle != NULL, GSL_ERROR_INTERNAL); g_return_val_if_fail (dhandle->ref_count > 0, GSL_ERROR_INTERNAL); GSL_SPIN_LOCK (&dhandle->mutex); if (dhandle->open_count == 0) { GslErrorType error; memset (&dhandle->setup, 0, sizeof (dhandle->setup)); error = dhandle->vtable->open (dhandle, &dhandle->setup); if (!error && (dhandle->setup.n_values < 0 || dhandle->setup.n_channels < 1 || dhandle->setup.bit_depth < 1)) { g_warning ("internal error in data handle open() (%p): nv=%ld nc=%u bd=%u", dhandle->vtable->open, dhandle->setup.n_values, dhandle->setup.n_channels, dhandle->setup.bit_depth); dhandle->vtable->close (dhandle); error = GSL_ERROR_INTERNAL; } if (error) { memset (&dhandle->setup, 0, sizeof (dhandle->setup)); GSL_SPIN_UNLOCK (&dhandle->mutex); return error; } dhandle->ref_count++; dhandle->open_count++; } else dhandle->open_count++; GSL_SPIN_UNLOCK (&dhandle->mutex); return GSL_ERROR_NONE; }
void _gsl_tick_stamp_inc (void) { volatile guint64 newstamp; guint64 systime; g_return_if_fail (global_tick_stamp_leaps > 0); systime = sfi_time_system (); newstamp = bse_engine_exvar_tick_stamp + global_tick_stamp_leaps; GSL_SPIN_LOCK (&global_tick_stamp_mutex); bse_engine_exvar_tick_stamp = newstamp; tick_stamp_system_time = systime; GSL_SPIN_UNLOCK (&global_tick_stamp_mutex); sfi_thread_emit_wakeups (newstamp); }
void gsl_data_handle_close (GslDataHandle *dhandle) { gboolean need_unref; g_return_if_fail (dhandle != NULL); g_return_if_fail (dhandle->ref_count > 0); g_return_if_fail (dhandle->open_count > 0); GSL_SPIN_LOCK (&dhandle->mutex); dhandle->open_count--; need_unref = !dhandle->open_count; if (!dhandle->open_count) dhandle->vtable->close (dhandle); GSL_SPIN_UNLOCK (&dhandle->mutex); if (need_unref) gsl_data_handle_unref (dhandle); }
void gsl_data_handle_unref (GslDataHandle *dhandle) { gboolean destroy; g_return_if_fail (dhandle != NULL); g_return_if_fail (dhandle->ref_count > 0); GSL_SPIN_LOCK (&dhandle->mutex); dhandle->ref_count--; destroy = dhandle->ref_count == 0; GSL_SPIN_UNLOCK (&dhandle->mutex); if (destroy) { g_return_if_fail (dhandle->open_count == 0); dhandle->vtable->destroy (dhandle); } }
void gsl_data_cache_close (GslDataCache *dcache) { gboolean need_unref; g_return_if_fail (dcache != NULL); g_return_if_fail (dcache->ref_count > 0); g_return_if_fail (dcache->open_count > 0); GSL_SPIN_LOCK (&dcache->mutex); dcache->open_count--; need_unref = !dcache->open_count; if (!dcache->open_count) { dcache->high_persistency = FALSE; gsl_data_handle_close (dcache->dhandle); } GSL_SPIN_UNLOCK (&dcache->mutex); if (need_unref) gsl_data_cache_unref (dcache); }
GslLong gsl_data_handle_read (GslDataHandle *dhandle, GslLong value_offset, GslLong n_values, gfloat *values) { GslLong l; g_return_val_if_fail (dhandle != NULL, -1); g_return_val_if_fail (dhandle->open_count > 0, -1); g_return_val_if_fail (value_offset >= 0, -1); if (n_values < 1) return 0; g_return_val_if_fail (values != NULL, -1); g_return_val_if_fail (value_offset < dhandle->setup.n_values, -1); n_values = MIN (n_values, dhandle->setup.n_values - value_offset); GSL_SPIN_LOCK (&dhandle->mutex); l = dhandle->vtable->read (dhandle, value_offset, n_values, values); GSL_SPIN_UNLOCK (&dhandle->mutex); return l; }
void gsl_data_cache_unref (GslDataCache *dcache) { g_return_if_fail (dcache != NULL); restart: g_return_if_fail (dcache->ref_count > 0); if (dcache->ref_count == 1) /* possible destruction, need global lock */ { g_return_if_fail (dcache->open_count == 0); GSL_SPIN_LOCK (&global_dcache_mutex); GSL_SPIN_LOCK (&dcache->mutex); if (dcache->ref_count != 1) { /* damn, some other thread trapped in, restart */ GSL_SPIN_UNLOCK (&dcache->mutex); GSL_SPIN_UNLOCK (&global_dcache_mutex); goto restart; } dcache->ref_count = 0; global_dcache_list = sfi_ring_remove (global_dcache_list, dcache); GSL_SPIN_UNLOCK (&dcache->mutex); global_dcache_count--; global_dcache_n_aged_nodes -= dcache->n_nodes; GSL_SPIN_UNLOCK (&global_dcache_mutex); dcache_free (dcache); } else { GSL_SPIN_LOCK (&dcache->mutex); if (dcache->ref_count < 2) { /* damn, some other thread trapped in, restart */ GSL_SPIN_UNLOCK (&dcache->mutex); goto restart; } dcache->ref_count--; GSL_SPIN_UNLOCK (&dcache->mutex); } }