#include #include #include #include #include #include #include #include "debug.h" #include "tests.h" #include "machine.h" #include "thread_map.h" #include "symbol.h" #include "thread.h" #define THREADS 4 static int go_away; struct thread_data { pthread_t pt; pid_t tid; void *map; int ready[2]; }; static struct thread_data threads[THREADS]; static int thread_init(struct thread_data *td) { void *map; map = mmap(NULL, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (map == MAP_FAILED) { perror("mmap failed"); return -1; } td->map = map; td->tid = syscall(SYS_gettid); pr_debug("tid = %d, map = %p\n", td->tid, map); return 0; } static void *thread_fn(void *arg) { struct thread_data *td = arg; ssize_t ret; int go; if (thread_init(td)) return NULL; /* Signal thread_create thread is initialized. */ ret = write(td->ready[1], &go, sizeof(int)); if (ret != sizeof(int)) { pr_err("failed to notify\n"); return NULL; } while (!go_away) { /* Waiting for main thread to kill us. */ usleep(100); } munmap(td->map, page_size); return NULL; } static int thread_create(int i) { struct thread_data *td = &threads[i]; int err, go; if (pipe(td->ready)) return -1; err = pthread_create(&td->pt, NULL, thread_fn, td); if (!err) { /* Wait for thread initialization. */ ssize_t ret = read(td->ready[0], &go, sizeof(int)); err = ret != sizeof(int); } close(td->ready[0]); close(td->ready[1]); return err; } static int threads_create(void) { struct thread_data *td0 = &threads[0]; int i, err = 0; go_away = 0; /* 0 is main thread */ if (thread_init(td0)) return -1; for (i = 1; !err && i < THREADS; i++) err = thread_create(i); return err; } static int threads_destroy(void) { struct thread_data *td0 = &threads[0]; int i, err = 0; /* cleanup the main thread */ munmap(td0->map, page_size); go_away = 1; for (i = 1; !err && i < THREADS; i++) err = pthread_join(threads[i].pt, NULL); return err; } typedef int (*synth_cb)(struct machine *machine); static int synth_all(struct machine *machine) { return perf_event__synthesize_threads(NULL, perf_event__process, machine, 0, 500); } static int synth_process(struct machine *machine) { struct thread_map *map; int err; map = thread_map__new_by_pid(getpid()); err = perf_event__synthesize_thread_map(NULL, map, perf_event__process, machine, 0, 500); thread_map__put(map); return err; } static int mmap_events(synth_cb synth) { struct machine *machine; int err, i; /* * The threads_create will not return before all threads * are spawned and all created memory map. * * They will loop until threads_destroy is called, so we * can safely run synthesizing function. */ TEST_ASSERT_VAL("failed to create threads", !threads_create()); machine = machine__new_host(); dump_trace = verbose > 1 ? 1 : 0; err = synth(machine); dump_trace = 0; TEST_ASSERT_VAL("failed to destroy threads", !threads_destroy()); TEST_ASSERT_VAL("failed to synthesize maps", !err); /* * All data is synthesized, try to find map for each * thread object. */ for (i = 0; i < THREADS; i++) { struct thread_data *td = &threads[i]; struct addr_location al; struct thread *thread; thread = machine__findnew_thread(machine, getpid(), td->tid); pr_debug("looking for map %p\n", td->map); thread__find_addr_map(thread, PERF_RECORD_MISC_USER, MAP__FUNCTION, (unsigned long) (td->map + 1), &al); thread__put(thread); if (!al.map) { pr_debug("failed, couldn't find map\n"); err = -1; break; } pr_debug("map %p, addr %" PRIx64 "\n", al.map, al.map->start); } machine__delete_threads(machine); machine__delete(machine); return err; } /* * This test creates 'THREADS' number of threads (including * main thread) and each thread creates memory map. * * When threads are created, we synthesize them with both * (separate tests): * perf_event__synthesize_thread_map (process based) * perf_event__synthesize_threads (global) * * We test we can find all memory maps via: * thread__find_addr_map * * by using all thread objects. */ int test__mmap_thread_lookup(int subtest __maybe_unused) { /* perf_event__synthesize_threads synthesize */ TEST_ASSERT_VAL("failed with sythesizing all", !mmap_events(synth_all)); /* perf_event__synthesize_thread_map synthesize */ TEST_ASSERT_VAL("failed with sythesizing process", !mmap_events(synth_process)); return 0; } selected='selected'>unified
authorMauro Carvalho Chehab <mchehab@s-opensource.com>2016-12-15 08:38:35 -0200
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-12-15 08:38:35 -0200
commit65390ea01ce678379da32b01f39fcfac4903f256 (patch)
tree7f849d66121533c331cf61136b124218d87cbf86 /sound/oss/swarm_cs4297a.c
parente7aa8c2eb11ba69b1b69099c3c7bd6be3087b0ba (diff)
parentd183e4efcae8d88a2f252e546978658ca6d273cc (diff)
Merge branch 'patchwork' into v4l_for_linus
* patchwork: (496 commits) [media] v4l: tvp5150: Add missing break in set control handler [media] v4l: tvp5150: Don't inline the tvp5150_selmux() function [media] v4l: tvp5150: Compile tvp5150_link_setup out if !CONFIG_MEDIA_CONTROLLER [media] em28xx: don't store usb_device at struct em28xx [media] em28xx: use usb_interface for dev_foo() calls [media] em28xx: don't change the device's name [media] mn88472: fix chip id check on probe [media] mn88473: fix chip id check on probe [media] lirc: fix error paths in lirc_cdev_add() [media] s5p-mfc: Add support for MFC v8 available in Exynos 5433 SoCs [media] s5p-mfc: Rework clock handling [media] s5p-mfc: Don't keep clock prepared all the time [media] s5p-mfc: Kill all IS_ERR_OR_NULL in clocks management code [media] s5p-mfc: Remove dead conditional code [media] s5p-mfc: Ensure that clock is disabled before turning power off [media] s5p-mfc: Remove special clock rate management [media] s5p-mfc: Use printk_ratelimited for reporting ioctl errors [media] s5p-mfc: Set DMA_ATTR_ALLOC_SINGLE_PAGES [media] vivid: Set color_enc on HSV formats [media] v4l2-tpg: Init hv_enc field with a valid value ...
Diffstat (limited to 'sound/oss/swarm_cs4297a.c')