diff --git a/.gitignore b/.gitignore index 5adf286..88d5aa3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .* !.gitignore !.travis.yml +!.valgrind.supp diff --git a/.valgrind.supp b/.valgrind.supp new file mode 100644 index 0000000..bf8efc5 --- /dev/null +++ b/.valgrind.supp @@ -0,0 +1,13 @@ +{ + libasound1 + Memcheck:Cond + obj:/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 +} + +{ + libasound2 + Memcheck:Param + ioctl(generic) + fun:ioctl + obj:/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0 +} diff --git a/Makefile b/Makefile index 11c1e15..e4afc34 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ ifneq ($(shell uname -s),Darwin) endif PACKAGES := gtk+-3.0 portaudio-2.0 fftw3f -CFLAGS += -Wall -O3 -ffast-math -DVERSION='"$(VERSION)"' `pkg-config --cflags $(PACKAGES)` +CFLAGS += -Wall -ffast-math -DVERSION='"$(VERSION)"' `pkg-config --cflags $(PACKAGES)` LDFLAGS += -lm -lpthread `pkg-config --libs $(PACKAGES)` SRCDIR := src @@ -40,6 +40,10 @@ test: $(BUILDDIR)/tg-dbg$(EXT) $(BUILDDIR)/tg-dbg test .PHONY: test +valgrind: $(BUILDDIR)/tg-vlg$(EXT) + valgrind --leak-check=full -v --num-callers=99 --suppressions=.valgrind.supp $(BUILDDIR)/tg-vlg$(EXT) +.PHONY: debug + $(BUILDDIR)/tg-timer.res: icons/tg-timer.rc icons/tg-timer.ico windres icons/tg-timer.rc -O coff -o $(BUILDDIR)/tg-timer.res @@ -54,12 +58,14 @@ ifeq ($(4),strip) endif endef -$(eval $(call TARGET,tg,,,strip)) -$(eval $(call TARGET,tg-lt,-DLIGHT,,strip)) -$(eval $(call TARGET,tg-dbg,-ggdb -DDEBUG,$(DEBUG_LDFLAGS),)) -$(eval $(call TARGET,tg-lt-dbg,-ggdb -DDEBUG -DLIGHT,$(DEBUG_LDFLAGS),)) -$(eval $(call TARGET,tg-prf,-pg,,)) -$(eval $(call TARGET,tg-lt-prf,-DLIGHT -pg,,)) +$(eval $(call TARGET,tg,-O3,,strip)) +$(eval $(call TARGET,tg-lt,-O3 -DLIGHT,,strip)) +$(eval $(call TARGET,tg-dbg,-O3 -ggdb -DDEBUG,$(DEBUG_LDFLAGS),)) +$(eval $(call TARGET,tg-lt-dbg,-O3 -ggdb -DDEBUG -DLIGHT,$(DEBUG_LDFLAGS),)) +$(eval $(call TARGET,tg-prf,-O3 -pg,,)) +$(eval $(call TARGET,tg-lt-prf,-O3 -DLIGHT -pg,,)) +$(eval $(call TARGET,tg-vlg,-O1 -g,,)) +$(eval $(call TARGET,tg-vlg-lt,-O1 -g -DLIGHT,,)) ICONSIZES := $(foreach SIZE, $(shell cat icons/sizes), $(SIZE)x$(SIZE)) diff --git a/src/algo.c b/src/algo.c index 6c3f390..5f64efd 100644 --- a/src/algo.c +++ b/src/algo.c @@ -103,6 +103,34 @@ void setup_buffers(struct processing_buffers *b) #endif } +void pb_destroy(struct processing_buffers *b) +{ + fftwf_free(b->samples); + free(b->samples_sc); + free(b->waveform); + free(b->waveform_sc); + fftwf_free(b->fft); + fftwf_free(b->sc_fft); + fftwf_free(b->tic_wf); + fftwf_free(b->slice_wf); + fftwf_free(b->tic_fft); + fftwf_free(b->slice_fft); + free(b->tic_c); + fftwf_destroy_plan(b->plan_a); + fftwf_destroy_plan(b->plan_b); + fftwf_destroy_plan(b->plan_c); + fftwf_destroy_plan(b->plan_d); + fftwf_destroy_plan(b->plan_e); + fftwf_destroy_plan(b->plan_f); + fftwf_destroy_plan(b->plan_g); + free(b->hpf); + free(b->lpf); + free(b->events); +#ifdef DEBUG + fftwf_free(b->debug); +#endif +} + struct processing_buffers *pb_clone(struct processing_buffers *p) { struct processing_buffers *new = malloc(sizeof(struct processing_buffers)); @@ -659,6 +687,13 @@ void setup_cal_data(struct calibration_data *cd) cd->events = malloc(cd->size * sizeof(uint64_t)); } +void cal_data_destroy(struct calibration_data *cd) +{ + free(cd->times); + free(cd->phases); + free(cd->events); +} + int add_sample_cal(struct processing_buffers *p, struct calibration_data *cd) { int i; @@ -732,7 +767,7 @@ void process(struct processing_buffers *p, int bph, double la) { prepare_data(p,1); p->ready = !compute_period(p,bph); - if(p->period >= p->sample_rate / 2) { + if(p->ready && p->period >= p->sample_rate / 2) { debug("Detected period too long\n"); p->ready = 0; } diff --git a/src/computer.c b/src/computer.c index 8b412f9..b4a0ee0 100644 --- a/src/computer.c +++ b/src/computer.c @@ -211,9 +211,28 @@ void *computing_thread(void *void_computer) } debug("Terminating computation thread\n"); + return NULL; } +void computer_destroy(struct computer *c) +{ + int i; + for(i=0; ipdata->buffers[i]); + free(c->pdata->buffers); + free(c->pdata); + cal_data_destroy(c->cdata); + free(c->cdata); + snapshot_destroy(c->actv); + if(c->curr) + snapshot_destroy(c->curr); + pthread_mutex_destroy(&c->mutex); + pthread_cond_destroy(&c->cond); + pthread_join(c->thread, NULL); + free(c); +} + struct computer *start_computer(int nominal_sr, int bph, double la, int cal) { struct processing_buffers *p = malloc(NSTEPS * sizeof(struct processing_buffers)); diff --git a/src/interface.c b/src/interface.c index 5a31479..fab2130 100644 --- a/src/interface.c +++ b/src/interface.c @@ -179,6 +179,8 @@ void computer_quit(void *w) gboolean quit(struct main_window *w) { + g_source_remove(w->kick_timeout); + g_source_remove(w->save_timeout); lock_computer(w->computer); w->computer->recompute = -1; w->computer->callback = computer_quit; @@ -590,8 +592,8 @@ int start_interface(GtkApplication* app, void *p) init_main_window(w); - g_timeout_add_full(G_PRIORITY_LOW,100,(GSourceFunc)kick_computer,w,NULL); - g_timeout_add_full(G_PRIORITY_LOW,10000,(GSourceFunc)save_on_change_timer,w,NULL); + w->kick_timeout = g_timeout_add_full(G_PRIORITY_LOW,100,(GSourceFunc)kick_computer,w,NULL); + w->save_timeout = g_timeout_add_full(G_PRIORITY_LOW,10000,(GSourceFunc)save_on_change_timer,w,NULL); #ifdef DEBUG if(testing) g_timeout_add_full(G_PRIORITY_LOW,3000,(GSourceFunc)quit,w,NULL); @@ -605,9 +607,12 @@ int start_interface(GtkApplication* app, void *p) void on_shutdown(GApplication *app, void *p) { debug("Main loop has terminated\n"); - save_config(g_object_get_data(G_OBJECT(app), "main-window")); + struct main_window *w = g_object_get_data(G_OBJECT(app), "main-window"); + save_config(w); + computer_destroy(w->computer); + op_destroy(w->active_panel); + free(w); terminate_portaudio(); - // We leak the main_window structure } int main(int argc, char **argv) diff --git a/src/tg.h b/src/tg.h index 66cda7f..25ce5dc 100644 --- a/src/tg.h +++ b/src/tg.h @@ -105,10 +105,12 @@ struct calibration_data { }; void setup_buffers(struct processing_buffers *b); +void pb_destroy(struct processing_buffers *b); struct processing_buffers *pb_clone(struct processing_buffers *p); void pb_destroy_clone(struct processing_buffers *p); void process(struct processing_buffers *p, int bph, double la); void setup_cal_data(struct calibration_data *cd); +void cal_data_destroy(struct calibration_data *cd); int test_cal(struct processing_buffers *p); int process_cal(struct processing_buffers *p, struct calibration_data *cd); @@ -180,6 +182,7 @@ struct computer { struct snapshot *snapshot_clone(struct snapshot *s); void snapshot_destroy(struct snapshot *s); +void computer_destroy(struct computer *c); struct computer *start_computer(int nominal_sr, int bph, double la, int cal); void lock_computer(struct computer *c); void unlock_computer(struct computer *c); @@ -237,6 +240,9 @@ struct main_window { GKeyFile *config_file; gchar *config_file_name; struct conf_data *conf_data; + + guint kick_timeout; + guint save_timeout; }; extern int preset_bph[];