├── .circleci └── config.yml ├── .cirrus.yml ├── .clang-format ├── .git-blame-ignore-revs ├── .github └── workflows │ └── CI.yml ├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── COPYING ├── Makefile.am ├── NEWS ├── README.affinity ├── README.md ├── SCHEDULING ├── clang-format.sh ├── cmake └── Findhwloc.cmake ├── include ├── 56reader-rwlock.h ├── fastcontext │ ├── 386-ucontext.h │ ├── arm-ucontext.h │ ├── power-ucontext.h │ └── taskimpl.h ├── maestro_sched.h ├── omp_affinity.h ├── qloop_innards.h ├── qt_addrstat.h ├── qt_affinity.h ├── qt_alloc.h ├── qt_arithmetic.h ├── qt_arrive_first.h ├── qt_asserts.h ├── qt_atomic_wait.h ├── qt_atomics.h ├── qt_barrier.h ├── qt_blocking_structs.h ├── qt_branching.h ├── qt_context.h ├── qt_envariables.h ├── qt_expect.h ├── qt_feb.h ├── qt_filters.h ├── qt_gcd.h ├── qt_hash.h ├── qt_hazardptrs.h ├── qt_initialized.h ├── qt_int_ceil.h ├── qt_int_log.h ├── qt_io.h ├── qt_locks.h ├── qt_macros.h ├── qt_mpool.h ├── qt_os.h ├── qt_output_macros.h ├── qt_prefetch.h ├── qt_profiling.h ├── qt_qthread_mgmt.h ├── qt_qthread_struct.h ├── qt_qthread_t.h ├── qt_queue.h ├── qt_shepherd_innards.h ├── qt_spawn_macros.h ├── qt_subsystems.h ├── qt_syncvar.h ├── qt_task_counter.h ├── qt_teams.h ├── qt_threadpool.h ├── qt_threadqueue_scheduler.h ├── qt_threadqueues.h ├── qt_threadstate.h ├── qt_touch.h ├── qt_visibility.h ├── qthread │ ├── .gitignore │ ├── allpairs.h │ ├── barrier.h │ ├── cacheline.h │ ├── common.h │ ├── dictionary.h │ ├── hash.h │ ├── io.h │ ├── logging.h │ ├── macros.h │ ├── omp_defines.h │ ├── qalloc.h │ ├── qarray.h │ ├── qdqueue.h │ ├── qlfqueue.h │ ├── qloop.h │ ├── qloop.hpp │ ├── qpool.h │ ├── qswsrqueue.h │ ├── qt_syscalls.h │ ├── qthread.h │ ├── qthread.hpp │ ├── qtimer.h │ ├── qutil.h │ ├── sinc.h │ ├── spr.h │ ├── syncvar.hpp │ ├── tls.h │ ├── top │ │ └── qthread.h │ └── wavefront.h ├── qthread_innards.h ├── rose_sinc_barrier.h └── spr_innards.h ├── man ├── htmlize.sh └── man3 │ ├── qalloc_checkpoint.3 │ ├── qalloc_cleanup.3 │ ├── qalloc_dynfree.3 │ ├── qalloc_dynmalloc.3 │ ├── qalloc_free.3 │ ├── qalloc_loadmap.3 │ ├── qalloc_makedynmap.3 │ ├── qalloc_makestatmap.3 │ ├── qalloc_malloc.3 │ ├── qalloc_statfree.3 │ ├── qalloc_statmalloc.3 │ ├── qarray_create.3 │ ├── qarray_create_configured.3 │ ├── qarray_create_tight.3 │ ├── qarray_destroy.3 │ ├── qarray_dist_like.3 │ ├── qarray_elem.3 │ ├── qarray_elem_migrate.3 │ ├── qarray_elem_nomigrate.3 │ ├── qarray_iter.3 │ ├── qarray_iter_constloop.3 │ ├── qarray_iter_loop.3 │ ├── qarray_iter_loop_nb.3 │ ├── qarray_iter_loopaccum.3 │ ├── qarray_set_shepof.3 │ ├── qarray_shepof.3 │ ├── qdqueue_create.3 │ ├── qdqueue_dequeue.3 │ ├── qdqueue_destroy.3 │ ├── qdqueue_empty.3 │ ├── qdqueue_enqueue.3 │ ├── qdqueue_enqueue_there.3 │ ├── qlfqueue_create.3 │ ├── qlfqueue_dequeue.3 │ ├── qlfqueue_destroy.3 │ ├── qlfqueue_empty.3 │ ├── qlfqueue_enqueue.3 │ ├── qpool_alloc.3 │ ├── qpool_create.3 │ ├── qpool_create_aligned.3 │ ├── qpool_destroy.3 │ ├── qpool_free.3 │ ├── qt_accept.3 │ ├── qt_allpairs.3 │ ├── qt_begin_blocking_action.3 │ ├── qt_connect.3 │ ├── qt_dictionary_create.3 │ ├── qt_dictionary_delete.3 │ ├── qt_dictionary_destroy.3 │ ├── qt_dictionary_end.3 │ ├── qt_dictionary_get.3 │ ├── qt_dictionary_iterator_copy.3 │ ├── qt_dictionary_iterator_create.3 │ ├── qt_dictionary_iterator_destroy.3 │ ├── qt_dictionary_iterator_equals.3 │ ├── qt_dictionary_iterator_get.3 │ ├── qt_dictionary_iterator_next.3 │ ├── qt_dictionary_put.3 │ ├── qt_dictionary_put_if_absent.3 │ ├── qt_double_max.3 │ ├── qt_double_min.3 │ ├── qt_double_prod.3 │ ├── qt_double_sum.3 │ ├── qt_end_blocking_action.3 │ ├── qt_int_max.3 │ ├── qt_int_min.3 │ ├── qt_int_prod.3 │ ├── qt_int_sum.3 │ ├── qt_loop.3 │ ├── qt_loop_balance.3 │ ├── qt_loop_balance_simple.3 │ ├── qt_loop_queue_addworker.3 │ ├── qt_loop_queue_create.3 │ ├── qt_loop_queue_run.3 │ ├── qt_loop_queue_run_there.3 │ ├── qt_loop_queue_setchunk.3 │ ├── qt_loop_step.3 │ ├── qt_loopaccum_balance.3 │ ├── qt_poll.3 │ ├── qt_pread.3 │ ├── qt_pwrite.3 │ ├── qt_read.3 │ ├── qt_select.3 │ ├── qt_sinc_create.3 │ ├── qt_sinc_destroy.3 │ ├── qt_sinc_expect.3 │ ├── qt_sinc_fini.3 │ ├── qt_sinc_init.3 │ ├── qt_sinc_reset.3 │ ├── qt_sinc_submit.3 │ ├── qt_sinc_wait.3 │ ├── qt_system.3 │ ├── qt_team_critical_section.3 │ ├── qt_team_eureka.3 │ ├── qt_team_id.3 │ ├── qt_team_parent_id.3 │ ├── qt_uint_max.3 │ ├── qt_uint_min.3 │ ├── qt_uint_prod.3 │ ├── qt_uint_sum.3 │ ├── qt_wait4.3 │ ├── qt_write.3 │ ├── qthread_cacheline.3 │ ├── qthread_cas.3 │ ├── qthread_cas_ptr.3 │ ├── qthread_dincr.3 │ ├── qthread_disable_shepherd.3 │ ├── qthread_disable_worker.3 │ ├── qthread_distance.3 │ ├── qthread_empty.3 │ ├── qthread_enable_shepherd.3 │ ├── qthread_enable_worker.3 │ ├── qthread_feb_barrier_create.3 │ ├── qthread_feb_barrier_destroy.3 │ ├── qthread_feb_barrier_enter.3 │ ├── qthread_feb_barrier_resize.3 │ ├── qthread_feb_status.3 │ ├── qthread_fill.3 │ ├── qthread_finalize.3 │ ├── qthread_fincr.3 │ ├── qthread_fork.3 │ ├── qthread_fork_precond.3 │ ├── qthread_fork_precond_to.3 │ ├── qthread_fork_syncvar.3 │ ├── qthread_fork_syncvar_to.3 │ ├── qthread_fork_to.3 │ ├── qthread_get_tasklocal.3 │ ├── qthread_id.3 │ ├── qthread_incr.3 │ ├── qthread_init.3 │ ├── qthread_initialize.3 │ ├── qthread_lock.3 │ ├── qthread_migrate_to.3 │ ├── qthread_num_shepherds.3 │ ├── qthread_num_workers.3 │ ├── qthread_queue_create.3 │ ├── qthread_queue_destroy.3 │ ├── qthread_queue_join.3 │ ├── qthread_queue_length.3 │ ├── qthread_queue_release_all.3 │ ├── qthread_queue_release_one.3 │ ├── qthread_readFE.3 │ ├── qthread_readFF.3 │ ├── qthread_readstate.3 │ ├── qthread_retloc.3 │ ├── qthread_shep.3 │ ├── qthread_shep_ok.3 │ ├── qthread_size_tasklocal.3 │ ├── qthread_sorted_sheps.3 │ ├── qthread_sorted_sheps_remote.3 │ ├── qthread_spawn.3 │ ├── qthread_stackleft.3 │ ├── qthread_syncvar_empty.3 │ ├── qthread_syncvar_fill.3 │ ├── qthread_syncvar_readFE.3 │ ├── qthread_syncvar_readFF.3 │ ├── qthread_syncvar_status.3 │ ├── qthread_syncvar_writeEF.3 │ ├── qthread_syncvar_writeEF_const.3 │ ├── qthread_syncvar_writeF.3 │ ├── qthread_syncvar_writeF_const.3 │ ├── qthread_unlock.3 │ ├── qthread_worker.3 │ ├── qthread_worker_unique.3 │ ├── qthread_writeEF.3 │ ├── qthread_writeEF_const.3 │ ├── qthread_writeF.3 │ ├── qthread_writeF_const.3 │ ├── qthread_yield.3 │ ├── qtimer_create.3 │ ├── qtimer_destroy.3 │ ├── qtimer_fastrand.3 │ ├── qtimer_secs.3 │ ├── qtimer_start.3 │ ├── qtimer_stop.3 │ ├── qutil_double_max.3 │ ├── qutil_double_min.3 │ ├── qutil_double_mult.3 │ ├── qutil_double_sum.3 │ ├── qutil_int_max.3 │ ├── qutil_int_min.3 │ ├── qutil_int_mult.3 │ ├── qutil_int_sum.3 │ ├── qutil_mergesort.3 │ ├── qutil_qsort.3 │ ├── qutil_uint_max.3 │ ├── qutil_uint_min.3 │ ├── qutil_uint_mult.3 │ └── qutil_uint_sum.3 ├── qthread-config.cmake.in ├── qthread.pc.in ├── src ├── .gitignore ├── CMakeLists.txt ├── affinity │ ├── README.binders │ ├── binders.c │ ├── common.c │ ├── hwloc.c │ ├── no.c │ ├── shepcomp.h │ └── shufflesheps.h ├── alloc │ ├── base.c │ └── chapel.c ├── barrier │ ├── array.c │ ├── feb.c │ ├── log.c │ └── sinc.c ├── cacheline.c ├── ds │ ├── dictionary │ │ ├── dictionary_shavit.c │ │ ├── dictionary_simple.c │ │ ├── dictionary_trie.c │ │ └── hash.c │ ├── qarray.c │ ├── qdqueue.c │ ├── qlfqueue.c │ ├── qpool.c │ └── qswsrqueue.c ├── envariables.c ├── fastcontext │ ├── COPYRIGHT │ ├── asm.S │ └── context.c ├── feb.c ├── hashmap.c ├── hazardptrs.c ├── io.c ├── lf_hashmap.c ├── locks.c ├── mpool.c ├── patterns │ ├── allpairs.c │ └── wavefront.c ├── qalloc.c ├── qloop.c ├── qthread.c ├── qtimer │ ├── gethrtime.c │ ├── gettime.c │ ├── gettimeofday.c │ └── mach.c ├── queue.c ├── qutil.c ├── shepherds.c ├── sincs │ ├── donecount.c │ ├── donecount_cas.c │ ├── original.c │ └── snzi.c ├── syncvar.c ├── syscalls │ ├── accept.c │ ├── connect.c │ ├── poll.c │ ├── pread.c │ ├── pwrite.c │ ├── read.c │ ├── select.c │ ├── system.c │ ├── user_defined.c │ ├── wait4.c │ └── write.c ├── teams.c ├── threadpool.c ├── threadqueues │ ├── distrib_threadqueues.c │ ├── nemesis_threadqueues.c │ └── sherwood_threadqueues.c ├── tls.c ├── touch.c └── workers.c ├── test ├── CMakeLists.txt ├── argparsing.h ├── basics │ ├── .gitignore │ ├── CMakeLists.txt │ ├── aligned_prodcons.c │ ├── aligned_purge_basic.c │ ├── aligned_purge_wakes.c │ ├── aligned_readXX_basic.c │ ├── aligned_writeFF_basic.c │ ├── aligned_writeFF_waits.c │ ├── arbitrary_blocking_operation.c │ ├── external_fork.c │ ├── external_syncvar.c │ ├── hello_world.c │ ├── hello_world_multi.c │ ├── qalloc.c │ ├── qthread_cacheline.c │ ├── qthread_cas.c │ ├── qthread_dincr.c │ ├── qthread_disable_shepherd.c │ ├── qthread_fincr.c │ ├── qthread_fork_precond.c │ ├── qthread_fp.c │ ├── qthread_fp_double.c │ ├── qthread_id.c │ ├── qthread_incr.c │ ├── qthread_migrate_to.c │ ├── qthread_readstate.c │ ├── qthread_stackleft.c │ ├── qthread_timer_wait.c │ ├── qtimer.c │ ├── queue.c │ ├── read.c │ ├── reinitialization.c │ ├── sinc.c │ ├── sinc_null.c │ ├── sinc_workers.c │ ├── syncvar_prodcons.c │ ├── tasklocal_data.c │ ├── tasklocal_data_no_argcopy.c │ ├── tasklocal_data_no_default.c │ ├── test_subteams.c │ └── test_teams.c ├── benchmarks │ ├── .gitignore │ ├── finepoints │ │ └── partSendPrototype │ │ │ ├── mpiBase.cc │ │ │ ├── mpiBaseTest1.cc │ │ │ ├── mpiBaseTest11.cc │ │ │ ├── mpiBaseTest2.cc │ │ │ ├── mpiBaseTest21.cc │ │ │ ├── mpiBaseTest21.cc.hs │ │ │ ├── mpiBaseTest3.cc │ │ │ ├── mpiBaseTest31.cc │ │ │ ├── mpiBaseTest31t.cc │ │ │ ├── mpiBaseTest32.cc │ │ │ ├── mpiBaseTest5.cc │ │ │ ├── mpiPart.cc │ │ │ ├── mpiPart.h │ │ │ └── osxbarrier.h │ ├── generic │ │ ├── time_chpl_spawn.c │ │ ├── time_febs.c │ │ ├── time_febs_graph_test.c │ │ ├── time_febs_stream_test.c │ │ ├── time_gcd.c │ │ ├── time_halo_swap_all.c │ │ ├── time_increments.c │ │ ├── time_prodcons_comm.c │ │ ├── time_producerconsumer.c │ │ ├── time_qt_loopaccums.c │ │ ├── time_qt_loops.c │ │ ├── time_stencil_bsp.c │ │ ├── time_stencil_feb.c │ │ ├── time_stencil_pre.c │ │ ├── time_syncvar_producerconsumer.c │ │ ├── time_thread_ring.c │ │ ├── time_threading.c │ │ └── time_threading.omp.c │ ├── mantevo │ │ └── hpccg │ │ │ ├── .gitignore │ │ │ ├── HPCCG.cpp │ │ │ ├── HPCCG.hpp │ │ │ ├── HPC_Sparse_Matrix.hpp │ │ │ ├── HPC_sparsemv.cpp │ │ │ ├── HPC_sparsemv.hpp │ │ │ ├── README │ │ │ ├── VERSION │ │ │ ├── compute_residual.cpp │ │ │ ├── compute_residual.hpp │ │ │ ├── ddot.cpp │ │ │ ├── ddot.hpp │ │ │ ├── exchange_externals.cpp │ │ │ ├── exchange_externals.hpp │ │ │ ├── generate_matrix.cpp │ │ │ ├── generate_matrix.hpp │ │ │ ├── loop_defines.h │ │ │ ├── main.cpp │ │ │ ├── make_local_matrix.cpp │ │ │ ├── make_local_matrix.hpp │ │ │ ├── mytimer.cpp │ │ │ ├── mytimer.hpp │ │ │ ├── read_HPC_row.cpp │ │ │ ├── read_HPC_row.hpp │ │ │ ├── waxpby.cpp │ │ │ └── waxpby.hpp │ ├── mt │ │ ├── time_cilk_eager_future.c │ │ ├── time_cilk_fib.c │ │ ├── time_cilk_task_spawn.c │ │ ├── time_eager_future.c │ │ ├── time_fib.c │ │ ├── time_fib2.c │ │ ├── time_omp_eager_future.c │ │ ├── time_omp_fib.c │ │ ├── time_omp_task_spawn.c │ │ ├── time_task_spawn.c │ │ ├── time_tbb_eager_future.cc │ │ ├── time_tbb_fib.cc │ │ └── time_tbb_task_spawn.cc │ ├── mtaap08 │ │ ├── time_chain_bench.c │ │ ├── time_chain_bench_pthread.c │ │ ├── time_cncthr_bench.c │ │ ├── time_cncthr_bench_pthread.c │ │ ├── time_incr_bench.c │ │ ├── time_incr_bench_pthread.c │ │ ├── time_lul_bench.c │ │ ├── time_lul_bench_pthread.c │ │ ├── time_mutex_bench.c │ │ ├── time_mutex_bench_pthread.c │ │ ├── time_spin_bench.c │ │ ├── time_spin_bench_pthread.c │ │ ├── time_thrcrt_bench.c │ │ └── time_thrcrt_bench_pthread.c │ ├── pmea09 │ │ ├── time_qarray.c │ │ ├── time_qarray_sizes.c │ │ ├── time_qdqueue.c │ │ ├── time_qdqueue_sizes.c │ │ ├── time_qlfqueue.c │ │ ├── time_qpool.c │ │ ├── time_tbbq.cpp │ │ └── time_tbbq_sizes.cpp │ ├── sc12 │ │ ├── fib_cilk.c │ │ ├── fib_omp.c │ │ ├── fib_qthreads.c │ │ ├── fib_tbb.cc │ │ ├── log.h │ │ ├── spawn_parallel_cilk.c │ │ ├── spawn_parallel_omp.c │ │ ├── spawn_parallel_qthreads.c │ │ ├── spawn_parallel_tbb.cc │ │ ├── spawn_sequential_cilk.c │ │ ├── spawn_sequential_omp.c │ │ ├── spawn_sequential_qthreads.c │ │ ├── spawn_sequential_tbb.cc │ │ ├── uts_cilk.c │ │ ├── uts_omp.c │ │ ├── uts_qthreads.c │ │ ├── uts_tbb.cc │ │ └── uts_tree_parameters.sh │ ├── thesis │ │ ├── time_allpairs.c │ │ ├── time_qutil_qsort.c │ │ └── time_wavefront.c │ └── uts │ │ ├── time_uts_aligned.c │ │ ├── time_uts_cilk.c │ │ ├── time_uts_donecount.c │ │ ├── time_uts_donecount2.c │ │ ├── time_uts_donecount3.c │ │ ├── time_uts_omp.c │ │ ├── time_uts_sample_trees.sh │ │ ├── time_uts_sinc.c │ │ ├── time_uts_syncvar.c │ │ └── time_uts_tbb.cc ├── features │ ├── .gitignore │ ├── CMakeLists.txt │ ├── allpairs.c │ ├── barrier.c │ ├── cxx_qt_loop.cpp │ ├── cxx_qt_loop_balance.cpp │ ├── guard_pages.c │ ├── qarray.c │ ├── qarray_accum.c │ ├── qdqueue.c │ ├── qlfqueue.c │ ├── qloop_utils.c │ ├── qpool.c │ ├── qswsrqueue.c │ ├── qt_dictionary.c │ ├── qt_loop.c │ ├── qt_loop_balance.c │ ├── qt_loop_balance_simple.c │ ├── qt_loop_balance_sinc.c │ ├── qt_loop_queue.c │ ├── qt_loop_simple.c │ ├── qt_loop_sinc.c │ ├── qutil.c │ ├── qutil_qsort.c │ ├── subteams.c │ └── wavefront.c ├── internal │ ├── CMakeLists.txt │ └── threadpool.c ├── stress │ ├── .gitignore │ ├── CMakeLists.txt │ ├── feb_as_fence.c │ ├── feb_prodcons_contended.c │ ├── feb_stream.c │ ├── lock_acq_rel.c │ ├── precond_fib.c │ ├── precond_spawn_simple.c │ ├── subteams_uts.c │ ├── syncvar_prodcons_contended.c │ ├── syncvar_stream.c │ ├── task_spawn.c │ └── test_spawn_simple.c └── utils │ ├── Makefile.am │ └── rng │ ├── .clang-format │ ├── .gitignore │ ├── AUTHORS │ ├── CMakeLists.txt │ ├── LICENSE │ ├── Makefile.am │ ├── brg_endian.h │ ├── brg_sha1.c │ ├── brg_sha1.h │ ├── brg_types.h │ ├── rng.h │ ├── rng_brg.c │ └── rng_brg.h └── userguide ├── examples ├── barrier.c ├── fib.c ├── fib_fast.c ├── fib_preconditioned.c ├── hello_world.c ├── hello_world_loop.c ├── hello_world_loop_optimized.c ├── hello_world_multiple.c ├── hello_world_safe.c ├── incr.c ├── loopaccum_balance.c ├── numworksheps.c ├── sinc.c ├── tcpserver.c └── worker_id.c ├── images ├── fib.png ├── fib_fast.png ├── fib_preconditioned.png ├── hello_world.png ├── hello_world_loop.png ├── hello_world_multiple.png ├── hello_world_optimized.png └── hello_world_safe.png └── userguide.tex /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | AllowShortBlocksOnASingleLine: Always 3 | AllowShortCaseLabelsOnASingleLine: true 4 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 5 | AllowShortLoopsOnASingleLine: true 6 | AlwaysBreakTemplateDeclarations: Yes 7 | AttributeMacros: ['Q_UNUSED', 'STACKLEFT_NOINLINE', 'API_FUNC'] 8 | BinPackArguments: false 9 | BinPackParameters: false 10 | BreakArrays: false 11 | BreakConstructorInitializers: AfterColon 12 | BreakInheritanceList: AfterColon 13 | ConstructorInitializerIndentWidth: 2 14 | ContinuationIndentWidth: 2 15 | EmptyLineBeforeAccessModifier: Never 16 | IncludeIsMainRegex: '' 17 | IndentCaseLabels: true 18 | InsertNewlineAtEOF: true 19 | KeepEmptyLinesAtTheStartOfBlocks: false 20 | KeepEmptyLinesAtEOF: true 21 | QualifierAlignment: Right 22 | RemoveSemicolon: true 23 | SeparateDefinitionBlocks: Always 24 | SortIncludes: CaseInsensitive 25 | SpaceBeforeCtorInitializerColon: false 26 | SpaceBeforeRangeBasedForLoopColon: false 27 | SpacesInContainerLiterals: false 28 | 29 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | 6901dc07127f54c060ec4046e21d05ccd7f437ab 2 | 3ddc9da40f8b34565c90d17ef83a9ef95a9deb18 3 | d1196d946c6551b205791f47ee952412e1a3e9bc 4 | 2368ba6baaeb986a16d7444edf412e3ef74296b4 5 | 163756c0337619255bb4b30a0b8ef21d17824aab 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | .deps 3 | stamp-h1 4 | Makefile 5 | Makefile.in 6 | configure 7 | config.log 8 | config.h 9 | libtool 10 | config.status 11 | config.cache 12 | autom4te.cache 13 | aclocal.m4 14 | .*.swp 15 | .*.swo 16 | .swp 17 | .swo 18 | tags 19 | cscope.out 20 | .fuse_* 21 | .autogen-version 22 | .autogen_git_output 23 | *.o 24 | *.lo 25 | .libs 26 | .dirstamp 27 | *.aux 28 | *.log 29 | *.gz 30 | .DS_Store 31 | *.pdf 32 | GPATH 33 | GRTAGS 34 | GTAGS 35 | *.trs 36 | *.log 37 | *~ 38 | activate.sh 39 | *.trs 40 | *.log 41 | *.test 42 | *.tar.bz2 43 | *.tar.gz 44 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | dstark:Dylan Stark 2 | rcmurph:Richard Murphy 3 | kbwheel:Kyle Wheeler 4 | bwbarre:Brian Barrett 5 | kbwheel@gmail.com:Kyle Wheeler 6 | allanporterfield@gmail.com:Allan Porterfield 7 | stephenolivier:Stephen Olivier 8 | debiddo99@gmail.com:David O'Brien 9 | gmackey:Greg Mackey 10 | bradcray:Brad Chamberlain 11 | nevans:Noah Evans 12 | janciesko:Jan Ciesko 13 | insertinterestingnamehere: Ian Henriksen 14 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12...3.31) 2 | 3 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 4 | 5 | set(CMAKE_C_STANDARD 11) 6 | set(BUILD_SHARED_LIBS ON CACHE BOOL "Build using shared libraries.") 7 | 8 | if(CMAKE_VERSION VERSION_LESS "3.9.0") 9 | project(qthreads 10 | VERSION 1.22 11 | DESCRIPTION "A user-level threading library" 12 | LANGUAGES C ASM CXX) 13 | else() 14 | project(qthreads 15 | VERSION 1.22 16 | LANGUAGES C ASM CXX) 17 | endif() 18 | 19 | include(GNUInstallDirs) 20 | include(CMakePackageConfigHelpers) 21 | 22 | set(THREADS_PREFER_PTHREAD_FLAG ON) 23 | find_package(Threads REQUIRED) 24 | 25 | add_subdirectory(src) 26 | 27 | if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) 28 | include(CTest) 29 | add_subdirectory(test) 30 | endif() 31 | 32 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | # 3 | # Copyright (c) 2008 Sandia Corporation 4 | # 5 | 6 | EXTRA_DIST = \ 7 | README.md \ 8 | README.affinity \ 9 | README.performance-monitoring.md \ 10 | SCHEDULING \ 11 | TODO.md \ 12 | autogen.sh 13 | 14 | pkgconfigdir = $(libdir)/pkgconfig 15 | pkgconfig_DATA = qthread.pc 16 | 17 | SUBDIRS = man include src test 18 | 19 | ACLOCAL_AMFLAGS = -I config 20 | 21 | DISTCHECK_CONFIGURE_FLAGS = $(EXTRA_DISTCHECK_OPTIONS) 22 | 23 | CONFIGURE_DEPENDENCIES = config/version-gen NEWS 24 | 25 | .PHONY: core buildtests tests benchmarks buildextra buildall basictests featuretests stresstests 26 | 27 | core: 28 | $(MAKE) -C src 29 | 30 | basictests: core 31 | $(MAKE) -C test basictests 32 | 33 | featuretests: core 34 | $(MAKE) -C test featuretests 35 | 36 | stresstests: core 37 | $(MAKE) -C test stresstests 38 | 39 | buildtests: tests 40 | 41 | tests: 42 | $(MAKE) -C src 43 | $(MAKE) -C test tests 44 | 45 | buildextra: benchmarks 46 | 47 | benchmarks: 48 | $(MAKE) -C src 49 | $(MAKE) -C test benchmarks 50 | 51 | buildall: 52 | $(MAKE) -C src 53 | $(MAKE) -C test buildall 54 | 55 | -------------------------------------------------------------------------------- /README.affinity: -------------------------------------------------------------------------------- 1 | CPU affinity is on by default, but depends on the available affinity and 2 | topology libraries. Essentially, the more information available about the 3 | machine, the better decisions can be made about affinity. 4 | 5 | The best-supported library is hwloc, which provides a full set of topology 6 | querying and thread- and memory-pinning functions on the widest variety of 7 | platforms, including Linux, BSD, and more. When using hwloc, the default 8 | arrangement is to pin each worker thread to a PU (the lowest level 9 | computational processing unit), and to group them (for the Sherwood scheduler) 10 | by the top-level cache. 11 | 12 | Binders is a low level affinity layer for precise control over where workers and 13 | shepherds are allocated. It is implemented as a colon-seperated list of 14 | cpustrings, where each cpustring is a shepherd. It is controlled by the 15 | environment variable QT_CPUBIND. See src/affinity/README.binders for more details. 16 | 17 | Unless hwloc is available, worker threads are NOT pinned. 18 | 19 | There are several environment variables that can be used to control CPU 20 | affinity and parallelism. See the qthread_initialize() man page for details. 21 | -------------------------------------------------------------------------------- /clang-format.sh: -------------------------------------------------------------------------------- 1 | find -iname *.h -or -iname *.c -or -iname *.hpp -or -iname *.cpp | xargs clang-format-20 -i 2 | -------------------------------------------------------------------------------- /cmake/Findhwloc.cmake: -------------------------------------------------------------------------------- 1 | find_path(hwloc_INCLUDE_DIR hwloc.h PATH_SUFFIXES include) 2 | find_library(hwloc_LIBRARY 3 | NAMES hwloc libhwloc 4 | PATH_SUFFIXES lib lib64 lib32) 5 | if("${hwloc_INCLUDE_DIR}" STREQUAL "hwloc_INCLUDE_DIR-NOTFOUND" OR "${hwloc_LIBRARY}" STREQUAL "hwloc_LIBRARY-NOTFOUND") 6 | set(hwloc_FOUND FALSE) 7 | else() 8 | set(hwloc_FOUND TRUE) 9 | endif() 10 | 11 | if(CMAKE_VERSION VERSION_LESS "3.17.0") 12 | message("-- Found hwloc: ${hwloc_FOUND}") 13 | else() 14 | message(STATUS "Found hwloc: ${hwloc_FOUND}") 15 | endif() 16 | -------------------------------------------------------------------------------- /include/fastcontext/arm-ucontext.h: -------------------------------------------------------------------------------- 1 | #include "qthread/common.h" 2 | #if (QTHREAD_ASSEMBLY_ARCH == QTHREAD_ARMV8_A64) 3 | #define NEEDARMA64CONTEXT 4 | #endif 5 | 6 | #include 7 | #include 8 | 9 | #include "qt_visibility.h" 10 | 11 | #define setcontext(u) qt_setmctxt(&(u)->mc) 12 | #define getcontext(u) qt_getmctxt(&(u)->mc) 13 | typedef struct mctxt mctxt_t; 14 | typedef struct uctxt uctxt_t; 15 | 16 | struct mctxt { 17 | /* Saved main processor registers. */ 18 | #ifdef NEEDARMA64CONTEXT 19 | uint64_t regs[32]; /* callee saves x0-x30, SP */ 20 | uint64_t fpu_regs[64]; /* 32 128bit FPU/SIMD Neon Registers */ 21 | #else 22 | uint32_t regs[16]; /* callee saves r0-r15 */ 23 | #endif 24 | char first; 25 | }; 26 | 27 | struct uctxt { 28 | struct { 29 | void *ss_sp; 30 | size_t ss_size; 31 | } uc_stack; 32 | 33 | // sigset_t uc_sigmask; 34 | mctxt_t mc; 35 | struct uctxt *uc_link; /* unused */ 36 | }; 37 | 38 | int INTERNAL qt_swapctxt(uctxt_t *, uctxt_t *); 39 | void INTERNAL qt_makectxt(uctxt_t *, void (*)(void), int, ...); 40 | int INTERNAL qt_getmctxt(mctxt_t *); 41 | void INTERNAL qt_setmctxt(mctxt_t *); 42 | /* vim:set expandtab: */ 43 | -------------------------------------------------------------------------------- /include/fastcontext/taskimpl.h: -------------------------------------------------------------------------------- 1 | #ifndef TASKIMPL_H 2 | #define TASKIMPL_H 3 | 4 | #include "qthread/common.h" 5 | 6 | #if (QTHREAD_ASSEMBLY_ARCH == QTHREAD_IA32) 7 | #define NEEDX86MAKECONTEXT 8 | #define NEEDSWAPCONTEXT 9 | #include "386-ucontext.h" 10 | #elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_AMD64) 11 | #define NEEDX86MAKECONTEXT 12 | #define NEEDSWAPCONTEXT 13 | #define NEEDX86REGISTERARGS 14 | #include "386-ucontext.h" 15 | #elif ((QTHREAD_ASSEMBLY_ARCH == QTHREAD_POWERPC32) || \ 16 | (QTHREAD_ASSEMBLY_ARCH == QTHREAD_POWERPC64)) 17 | #define NEEDPOWERMAKECONTEXT 18 | #define NEEDSWAPCONTEXT 19 | #include "power-ucontext.h" 20 | #elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_ARM) 21 | #include 22 | #define NEEDARMMAKECONTEXT 23 | #define NEEDSWAPCONTEXT 24 | #include "arm-ucontext.h" 25 | #elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_ARMV8_A64) 26 | #include 27 | #define NEEDARMA64MAKECONTEXT 28 | #define NEEDSWAPCONTEXT 29 | #include "arm-ucontext.h" 30 | #else 31 | #error This platform has no fastcontext support 32 | #endif 33 | 34 | #endif // ifndef TASKIMPL_H 35 | /* vim:set expandtab: */ 36 | -------------------------------------------------------------------------------- /include/maestro_sched.h: -------------------------------------------------------------------------------- 1 | #ifndef MAESTRO_SCHED_H 2 | #define MAESTRO_SCHED_H 3 | 4 | enum trigger_type { 5 | MTT_CORE = 1, 6 | MTT_SOCKET = 2, 7 | MTT_SYSTEM = 3, 8 | MTT_OTHER = 0 9 | }; 10 | 11 | enum trigger_action { 12 | MTA_LOWER_STREAM_COUNT = 1, 13 | MTA_RAISE_STREAM_COUNT = 2, 14 | MTA_OTHER = 0 15 | }; 16 | 17 | void maestro_sched(enum trigger_type type, enum trigger_action action, int val); 18 | int maestro_allowed_workers(void); 19 | int maestro_current_workers(int val); 20 | int64_t maestro_size(void); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/omp_affinity.h: -------------------------------------------------------------------------------- 1 | #ifndef OMP_AFFINITY_H 2 | #define OMP_AFFINITY_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #ifdef QTHREAD_OMP_AFFINITY 11 | 12 | // Stealing modes 13 | #define QTHREAD_STEAL_ON_ANY_IDLE 0 14 | #define QTHREAD_STEAL_ON_ALL_IDLE 1 15 | 16 | #define OMP_NO_CHILD_TASK_AFFINITY -1 17 | 18 | unsigned int qthread_shepherds_available(void); 19 | 20 | void qthread_disable_stealing(void); 21 | 22 | void qthread_disable_stealing_onshep(unsigned int shep); 23 | 24 | void qthread_disable_stealing_all(void); 25 | 26 | void qthread_enable_stealing(unsigned int stealing_mode); 27 | 28 | void qthread_enable_stealing_on_shep(unsigned int shep, 29 | unsigned int stealing_mode); 30 | 31 | void qthread_enable_stealing_all(unsigned int stealing_mode); 32 | 33 | void omp_child_task_affinity(unsigned int shep); 34 | 35 | void *omp_affinity_alloc(size_t bytes); 36 | void *omp_affinity_alloc_onshep(size_t bytes, unsigned int shep); 37 | void omp_affinity_mem_toshep(void *addr, size_t bytes, unsigned int shep); 38 | void omp_affinity_free(void *ptr, size_t bytes); 39 | 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/qt_addrstat.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_ADDRSTAT_H 2 | #define QT_ADDRSTAT_H 3 | 4 | #include "qt_blocking_structs.h" 5 | 6 | /* This allocates a new, initialized addrstat structure, which is used for 7 | * keeping track of the FEB status of an address. It expects a shepherd pointer 8 | * to use to find the right memory pool to use. */ 9 | static inline qthread_addrstat_t *qthread_addrstat_new(void) { 10 | qthread_addrstat_t *ret = ALLOC_ADDRSTAT(); 11 | QTHREAD_FASTLOCK_INIT_PTR(&ret->lock); 12 | QTHREAD_FASTLOCK_LOCK(&ret->lock); 13 | ret->full = 1; 14 | ret->valid = 1; 15 | ret->EFQ = NULL; 16 | ret->FEQ = NULL; 17 | ret->FFQ = NULL; 18 | ret->FFWQ = NULL; 19 | QTHREAD_FASTLOCK_UNLOCK(&ret->lock); 20 | 21 | return ret; 22 | } 23 | 24 | /* this function is for maintenance of the FEB hashtables. SHOULD only be 25 | * necessary for things left over when qthread_finalize is called */ 26 | static void qthread_addrstat_delete(void *m_void) { 27 | qthread_addrstat_t *m = (qthread_addrstat_t *)m_void; 28 | QTHREAD_FASTLOCK_DESTROY(m->lock); 29 | FREE_ADDRSTAT(m); 30 | } 31 | 32 | #endif // ifndef QT_ADDRSTAT_H 33 | /* vim:set expandtab: */ 34 | -------------------------------------------------------------------------------- /include/qt_alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_ALLOC_H 2 | #define QT_ALLOC_H 3 | 4 | #include 5 | #include 6 | 7 | #include "qt_visibility.h" 8 | 9 | void INTERNAL *qt_malloc(size_t size); 10 | 11 | void INTERNAL qt_free(void *ptr); 12 | 13 | #define MALLOC(sz) qt_malloc(sz) 14 | #define FREE(ptr, sz) qt_free(ptr) 15 | 16 | void INTERNAL *qt_calloc(size_t nmemb, size_t size); 17 | 18 | void INTERNAL *qt_realloc(void *ptr, size_t size); 19 | 20 | void INTERNAL *qt_internal_aligned_alloc(size_t alloc_size, 21 | uint_fast16_t alignment); 22 | void INTERNAL qt_internal_aligned_free(void *ptr, uint_fast16_t alignment); 23 | 24 | void INTERNAL qt_internal_alignment_init(void); 25 | 26 | #ifdef __INTEL_COMPILER 27 | #pragma warning(disable : 191) 28 | #endif 29 | extern size_t _pagesize; 30 | #define pagesize ((size_t)_pagesize) 31 | #endif // ifndef QT_ALLOC_H 32 | /* vim:set expandtab: */ 33 | -------------------------------------------------------------------------------- /include/qt_arithmetic.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_ARITHMETIC_H 2 | #define QT_ARITHMETIC_H 3 | 4 | // Miscellanious aritmetic utility macros. 5 | #define QTHREAD_MAX(a, b) (((a) > (b)) ? (a) : (b)) 6 | #define QTHREAD_MIN(a, b) (((a) < (b)) ? (a) : (b)) 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/qt_arrive_first.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_ARRIVEFIRST_H 2 | #define QT_ARRIVEFIRST_H 3 | 4 | #include "qthread/qthread.h" 5 | 6 | struct qt_arrive_first_s { 7 | size_t activeSize; /* size of barrier */ 8 | size_t allocatedSize; /* lowest size power of 2 equal or bigger than barrier 9 | -- for allocations */ 10 | int64_t doneLevel; /* height of the tree */ 11 | int64_t nestLock; /* backup for nested situations */ 12 | char arriveFirstDebug; /* flag to turn on internal printf debugging */ 13 | int64_t volatile **present; /* array of counters to track who's arrived */ 14 | }; 15 | 16 | typedef struct qt_arrive_first_s qt_arrive_first_t; 17 | 18 | /* visible function calls */ 19 | int64_t qt_global_arrive_first(qthread_shepherd_id_t const shep); 20 | void qt_global_arrive_first_destroy(void); 21 | void qt_global_arrive_first_init(int size, int debug); 22 | void qtar_resize(aligned_t s); /* reset the size of the psuedo barrier */ 23 | aligned_t qtar_size(void); /* how big is current psuedo barrier */ 24 | void qtar_dump(qt_arrive_first_t *b); /* debugging function -- dump */ 25 | /* internal structure of b */ 26 | 27 | #define qt_arrive_first(x) qt_global_arrive_first(x) 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /include/qt_barrier.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_BARRIER_H 2 | #define QT_BARRIER_H 3 | 4 | #include "qt_visibility.h" 5 | 6 | /* these two calls assume that we're using a/the global barrier */ 7 | void qt_global_barrier(void); 8 | void qt_global_barrier_init(size_t size, int debug); 9 | void qt_global_barrier_destroy(void); 10 | void qt_global_barrier_resize(size_t size); 11 | // #define qt_barrier(x) qt_global_barrier() 12 | 13 | void INTERNAL qt_barrier_internal_init(void); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/qt_branching.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_BRANCHING_H 2 | #define QT_BRANCHING_H 3 | 4 | #define likely(x) (__builtin_expect(!!(x), 1)) 5 | #define unlikely(x) (__builtin_expect(!!(x), 0)) 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /include/qt_context.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_CONTEXT_H 2 | #define QT_CONTEXT_H 3 | 4 | #if defined(USE_SYSTEM_SWAPCONTEXT) 5 | #include /* for ucontext_t */ 6 | typedef ucontext_t qt_context_t; 7 | #else 8 | #include "fastcontext/taskimpl.h" 9 | typedef uctxt_t qt_context_t; 10 | #endif 11 | 12 | #endif // ifndef QT_CONTEXT_H 13 | /* vim:set expandtab: */ 14 | -------------------------------------------------------------------------------- /include/qt_envariables.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_ENVARIABLES_H 2 | #define QT_ENVARIABLES_H 3 | 4 | #include "qt_visibility.h" 5 | 6 | char const INTERNAL *qt_internal_get_env_str(char const *envariable, 7 | char const *dflt); 8 | unsigned long INTERNAL qt_internal_get_env_num(char const *envariable, 9 | unsigned long dflt, 10 | unsigned long zerodflt); 11 | unsigned char INTERNAL qt_internal_get_env_bool(char const *envariable, 12 | unsigned char dflt); 13 | int INTERNAL qt_internal_unset_envstr(char const *envariable); 14 | #endif // ifndef QT_ENVARIABLES_H 15 | /* vim:set expandtab: */ 16 | -------------------------------------------------------------------------------- /include/qt_expect.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_EXPECT_H 2 | #define QTHREAD_EXPECT_H 3 | 4 | #define QTHREAD_EXPECT(x, y) __builtin_expect(!!(x), (y)) 5 | #define QTHREAD_LIKELY(x) __builtin_expect(!!(x), 1) 6 | #define QTHREAD_UNLIKELY(x) __builtin_expect(!!(x), 0) 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/qt_filters.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_FILTERS_H 2 | #define QT_FILTERS_H 3 | 4 | typedef enum _filter_code { 5 | IGNORE_AND_CONTINUE, 6 | IGNORE_AND_STOP, 7 | REMOVE_AND_CONTINUE, 8 | REMOVE_AND_STOP 9 | } filter_code; 10 | 11 | #endif 12 | /* vim:set expandtab: */ 13 | -------------------------------------------------------------------------------- /include/qt_gcd.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static inline size_t qt_gcd(size_t a, size_t b) { 4 | #ifdef QTHREAD_SHIFT_GCD 5 | size_t k = 0; 6 | if (a == 0) return b; 7 | if (b == 0) return a; 8 | while ((a & 1) == 0 && (b & 1) == 0) { /* while they're both even */ 9 | a >>= 1; /* divide by 2 */ 10 | b >>= 1; /* divide by 2 */ 11 | k++; /* power of 2 to the result */ 12 | } 13 | /* now, one or the other is odd */ 14 | do { 15 | if ((a & 1) == 0) a >>= 1; 16 | else if ((b & 1) == 0) b >>= 1; 17 | else if (a >= b) /* both odd */ a = (a - b) >> 1; 18 | else b = (b - a) >> 1; 19 | } while (a > 0); 20 | return b << k; 21 | #else /* MOD GCD */ 22 | while (1) { 23 | if (a == 0) return b; 24 | b %= a; 25 | if (b == 0) return a; 26 | a %= b; 27 | } 28 | #endif 29 | } 30 | 31 | static inline size_t qt_lcm(size_t a, size_t b) { 32 | size_t tmp = qt_gcd(a, b); 33 | /* on 32 bit platforms, it's pretty easy for a * b to overflow so we force 34 | * 64 bit multiplication*/ 35 | uint64_t largeA = a; 36 | uint64_t largeB = b; 37 | return (tmp != 0) ? (largeA * largeB / tmp) : 0; 38 | } 39 | -------------------------------------------------------------------------------- /include/qt_hazardptrs.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_HAZARDPTRS_H 2 | #define QT_HAZARDPTRS_H 3 | 4 | #include "qt_visibility.h" 5 | 6 | #define HAZARD_PTRS_PER_SHEP 2 7 | 8 | typedef struct { 9 | void (*freefunc)(void *); 10 | void *ptr; 11 | } hazard_freelist_entry_t; 12 | 13 | typedef struct { 14 | hazard_freelist_entry_t *freelist; 15 | unsigned int count; 16 | } hazard_freelist_t; 17 | 18 | void INTERNAL initialize_hazardptrs(void); 19 | void INTERNAL hazardous_ptr(unsigned int which, void *ptr); 20 | 21 | typedef void (*hazardous_free_f)(void *arg); 22 | void INTERNAL hazardous_release_node(hazardous_free_f freefunc, void *ptr); 23 | 24 | #endif // ifndef QT_HAZARDPTRS_H 25 | /* vim:set expandtab: */ 26 | -------------------------------------------------------------------------------- /include/qt_initialized.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_INITIALIZED_H 2 | #define QT_INITIALIZED_H 3 | 4 | extern int qthread_library_initialized; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/qt_int_ceil.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_INT_CEIL_H 2 | #define QT_INT_CEIL_H 3 | 4 | #define QT_CEIL_RATIO(x, y) (1 + (((x) - 1) / (y))) 5 | #define QT_CEIL_POW2(x, y) (((x) + ((1 << (y)) - 1)) >> (y)) 6 | #define QT_CEIL_DIV8(x) (((x) + 7) >> 3) 7 | 8 | #endif 9 | /* vim:set expandtab: */ 10 | -------------------------------------------------------------------------------- /include/qt_int_log.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_INT_LOG_H 2 | #define QT_INT_LOG_H 3 | 4 | /* This public-domain algorithm from 5 | * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog */ 6 | 7 | static char const LogTable256[256] = { 8 | #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n 9 | (char)-1, 0, 1, 1, 2, 2, 2, 2, 10 | 3, 3, 3, 3, 3, 3, 3, 3, 11 | LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6), LT(7), 12 | LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)}; 13 | 14 | static inline uint32_t QT_INT_LOG(uint32_t v) { 15 | uint32_t r; 16 | uint32_t t; 17 | uint32_t tt; 18 | 19 | if ((tt = (v >> 16))) { 20 | r = (t = tt >> 8) ? 24 + LogTable256[t] : 16 + LogTable256[tt]; 21 | } else { 22 | r = (t = v >> 8) ? 8 + LogTable256[t] : LogTable256[v]; 23 | } 24 | return r; 25 | } 26 | 27 | #endif // ifndef QT_INT_LOG_H 28 | /* vim:set expandtab: */ 29 | -------------------------------------------------------------------------------- /include/qt_io.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_IO_H 2 | #define QT_IO_H 3 | 4 | /* System Headers */ 5 | #include "stdlib.h" /* malloc() and free() */ 6 | 7 | /* Public Headers */ 8 | #include "qthread/io.h" 9 | 10 | /* Internal Headers */ 11 | #include "qt_blocking_structs.h" 12 | #include "qt_qthread_mgmt.h" 13 | #include "qt_qthread_struct.h" 14 | 15 | #define ALLOC_SYSCALLJOB() qt_mpool_alloc(syscall_job_pool); 16 | #define FREE_SYSCALLJOB(j) qt_mpool_free(syscall_job_pool, j); 17 | 18 | extern qt_mpool syscall_job_pool; 19 | 20 | void qt_blocking_subsystem_init(void); 21 | int qt_process_blocking_call(void); 22 | void qt_blocking_subsystem_enqueue(qt_blocking_queue_node_t *job); 23 | 24 | static inline int qt_blockable(void) { 25 | qthread_t *t = qthread_internal_self(); 26 | 27 | if ((t != NULL) && 28 | atomic_load_explicit(&t->flags, memory_order_relaxed) & QTHREAD_SIMPLE) { 29 | t = NULL; 30 | } 31 | return (t != NULL); 32 | } 33 | #endif // ifndef QT_IO_H 34 | /* vim:set expandtab: */ 35 | -------------------------------------------------------------------------------- /include/qt_locks.h: -------------------------------------------------------------------------------- 1 | #ifndef _QT_LOCKS_H_ 2 | #define _QT_LOCKS_H_ 3 | #include "qt_visibility.h" 4 | 5 | int INTERNAL spinlocks_finalize(void); 6 | int INTERNAL spinlocks_initialize(void); 7 | 8 | #endif // _QT_LOCKS_H_ 9 | 10 | -------------------------------------------------------------------------------- /include/qt_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_MACROS_H 2 | #define QT_MACROS_H 3 | 4 | // Work around OSX currently refusing to support threads.h 5 | #if 201112L <= __STDC_VERSION__ && __STDC_VERSION__ < 202311L 6 | #ifndef __STDC_NO_THREADS__ 7 | #include 8 | #else 9 | #define thread_local _Thread_local 10 | #endif 11 | #elif __STDC_VERSION__ < 201112L 12 | #error "C11 is required" 13 | #endif 14 | 15 | #ifdef __GNUC__ 16 | #define Q_UNUSED(x) __attribute__((unused)) x 17 | #else 18 | #define Q_UNUSED(x) x 19 | #endif 20 | 21 | #if defined(__has_feature) 22 | #if __has_feature(memory_sanitizer) 23 | #define QTHREAD_MSAN 24 | #endif 25 | #endif 26 | #ifdef QTHREAD_MSAN 27 | #define QTHREAD_SUPPRESS_MSAN __attribute__((no_sanitize("memory"))) 28 | #else 29 | #define QTHREAD_SUPPRESS_MSAN 30 | #endif 31 | 32 | #define TLS_DECL(type, name) thread_local type name 33 | #define TLS_DECL_INIT(type, name) thread_local type name = 0 34 | #define TLS_GET(name) name 35 | #define TLS_SET(name, val) name = (val) 36 | #define TLS_INIT(name) 37 | #define TLS_INIT2(name, func) 38 | #define TLS_DELETE(name) name = 0 39 | 40 | #endif // ifndef QT_MACROS_H 41 | /* vim:set expandtab: */ 42 | -------------------------------------------------------------------------------- /include/qt_mpool.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_MPOOL_H 2 | #define QT_MPOOL_H 3 | 4 | #include /* for size_t (according to C89) */ 5 | 6 | typedef struct qt_mpool_s *qt_mpool; 7 | 8 | void *qt_mpool_alloc(qt_mpool pool); 9 | 10 | void qt_mpool_free(qt_mpool pool, void *mem); 11 | 12 | #define qt_mpool_create(item_size) qt_mpool_create_aligned((item_size), 0) 13 | 14 | qt_mpool qt_mpool_create_aligned(size_t item_size, size_t const alignment); 15 | void qt_mpool_destroy(qt_mpool pool); 16 | 17 | void qt_mpool_subsystem_init(void); 18 | 19 | #endif // ifndef QT_MPOOL_H 20 | /* vim:set expandtab: */ 21 | -------------------------------------------------------------------------------- /include/qt_os.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_OS_H 2 | #define QT_OS_H 3 | 4 | // Not all Operating systems listed here are actually supported. 5 | 6 | #if defined(__linux__) || defined(QTHREADS_LINUX) 7 | #ifndef QTHREADS_LINUX 8 | #define QTHREADS_LINUX 9 | #endif 10 | 11 | #elif defined(__APPLE__) || defined(QTHREADS_APPLE) 12 | #ifndef QTHREADS_APPLE 13 | #define QTHREADS_APPLE 14 | #endif 15 | 16 | #elif defined(_WIN32) || defined(QTHREADS_WINDOWS) 17 | #ifndef QTHREADS_WINDOWS 18 | #define QTHREADS_WINDOWS 19 | #endif 20 | 21 | #elif defined(__FreeBSD__) || defined(QTHREADS_FREEBSD) 22 | #ifndef QTHREADS_FREEBSD 23 | #define QTHREADS_FREEBSD 24 | #endif 25 | 26 | #elif defined(__NetBSD__) || defined(QTHREADS_NETBSD) 27 | #ifndef QTHREADS_NETBSD 28 | #define QTHREADS_NETBSD 29 | #endif 30 | 31 | #elif defined(__OpenBSD__) || defined(QTHREADS_OPENBSD) 32 | #ifndef QTHREADS_OPENBSD 33 | #define QTHREADS_OPENBSD 34 | #endif 35 | 36 | #elif defined(__DragonFly__) || defined(QTHREADS_DRAGONFLYBSD) 37 | #ifndef QTHREADS_DRAGONFLYBSD 38 | #define QTHREADS_DRAGONFLYBSD 39 | #endif 40 | 41 | #elif defined(__sun) 42 | #error "Sun OS not currently supported." 43 | 44 | #else 45 | #error "Unrecognized OS" 46 | 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /include/qt_output_macros.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_OUTPUT_MACROS_H 2 | #define QT_OUTPUT_MACROS_H 3 | 4 | #include 5 | 6 | #define print_status(format, ...) printf("QTHREADS: " format, ##__VA_ARGS__) 7 | #define print_warning(format, ...) \ 8 | fprintf(stderr, "QTHREADS: " format, ##__VA_ARGS__) 9 | #define print_error(format, ...) \ 10 | do { \ 11 | fprintf(stderr, "QTHREADS ERROR: " format, ##__VA_ARGS__); \ 12 | fflush(stderr); \ 13 | } while (0) 14 | 15 | #endif 16 | /* vim:set expandtab: */ 17 | -------------------------------------------------------------------------------- /include/qt_prefetch.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_PREFETCH_H 2 | #define QTHREAD_PREFETCH_H 3 | 4 | #ifdef __GNUC__ 5 | #define Q_PREFETCH(x, ...) __builtin_prefetch((x), ##__VA_ARGS__) 6 | #else 7 | #define Q_PREFETCH(x, ...) 8 | #endif 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/qt_profiling.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_PROFILING_H 2 | #define QT_PROFILING_H 3 | 4 | #ifdef QTHREAD_COUNT_THREADS 5 | #define QTHREAD_COUNT_THREADS_BINCOUNTER(TYPE, BIN) \ 6 | qthread_internal_incr(&TYPE##_stripes[(BIN)], &TYPE##_stripes_locks[(BIN)], 1) 7 | #else 8 | #define QTHREAD_COUNT_THREADS_BINCOUNTER(TYPE, BIN) \ 9 | do { \ 10 | } while (0) 11 | #endif 12 | 13 | #endif // ifndef QT_PROFILING_H 14 | /* vim:set expandtab: */ 15 | -------------------------------------------------------------------------------- /include/qt_qthread_mgmt.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_QTHREAD_MGMT_H 2 | #define QT_QTHREAD_MGMT_H 3 | 4 | #include "qt_qthread_t.h" 5 | #include "qt_visibility.h" 6 | 7 | void INTERNAL qthread_thread_free(qthread_t *t); 8 | qthread_t INTERNAL *qthread_internal_self(void); 9 | 10 | #endif 11 | /* vim:set expandtab: */ 12 | -------------------------------------------------------------------------------- /include/qt_qthread_t.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_QTHREAD_T_H 2 | #define QT_QTHREAD_T_H 3 | 4 | typedef struct qthread_s qthread_t; 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/qt_subsystems.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_SUBSYSTEMS_H 2 | #define QT_SUBSYSTEMS_H 3 | 4 | #include "qt_visibility.h" 5 | 6 | void INTERNAL qthread_internal_cleanup(void (*function)(void)); 7 | void INTERNAL qthread_internal_cleanup_early(void (*function)(void)); 8 | void INTERNAL qthread_internal_cleanup_late(void (*function)(void)); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/qt_task_counter.h: -------------------------------------------------------------------------------- 1 | #ifndef _QT_TASK_COUNTER_H_ 2 | #define _QT_TASK_COUNTER_H_ 3 | 4 | #include 5 | 6 | #if QTHREAD_BITS == 32 7 | 8 | #define QT_TCOUNT_OFFSET (31) 9 | #define QT_TCOUNT_BASE (1u) 10 | 11 | #elif QTHREAD_BITS == 64 12 | 13 | #define QT_TCOUNT_OFFSET (63) 14 | #define QT_TCOUNT_BASE (1ul) 15 | 16 | #else 17 | 18 | #error "Don't know type for sizeof aligned_t" 19 | 20 | #endif 21 | 22 | static aligned_t const tcount_waiting_mask = 23 | (QT_TCOUNT_BASE << QT_TCOUNT_OFFSET); 24 | static aligned_t const tcount_children_mask = 25 | ((QT_TCOUNT_BASE << QT_TCOUNT_OFFSET) - QT_TCOUNT_BASE); 26 | static aligned_t const tcount_finished_state = 27 | (QT_TCOUNT_BASE << QT_TCOUNT_OFFSET); 28 | 29 | static inline aligned_t tcount_create(aligned_t waiting, aligned_t children) { 30 | return ((waiting << QT_TCOUNT_OFFSET) + children); 31 | } 32 | 33 | static inline aligned_t tcount_get_waiting(aligned_t counter) { 34 | return (counter >> QT_TCOUNT_OFFSET); 35 | } 36 | 37 | static inline aligned_t tcount_get_children(aligned_t counter) { 38 | return (counter & tcount_children_mask); 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /include/qt_threadpool.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_THREADPOOL_H 2 | #define QT_THREADPOOL_H 3 | 4 | #include 5 | 6 | #include 7 | 8 | typedef int (*qt_threadpool_func_type)(void *); 9 | 10 | typedef enum { 11 | POOL_INIT_SUCCESS, 12 | POOL_INIT_ALREADY_INITIALIZED, 13 | POOL_INIT_NO_THREADS_SPECIFIED, 14 | POOL_INIT_OUT_OF_MEMORY, 15 | // TODO: better granularity when forwarding errors from thread creation. 16 | POOL_INIT_ERROR 17 | } hw_pool_init_status; 18 | 19 | hw_pool_init_status hw_pool_init(uint32_t num_threads); 20 | void hw_pool_destroy(); 21 | void hw_pool_run_on_all(qt_threadpool_func_type func, void *arg); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/qt_threadqueue_scheduler.h: -------------------------------------------------------------------------------- 1 | #ifndef _QT_THREADQUEUE_SCHEDULER_H_ 2 | #define _QT_THREADQUEUE_SCHEDULER_H_ 3 | #include "qt_shepherd_innards.h" 4 | 5 | qthread_shepherd_id_t INTERNAL 6 | qt_threadqueue_choose_dest(qthread_shepherd_t *curr_shep); 7 | 8 | #endif // _QT_THREADQUEUE_SCHEDULER_H_ 9 | 10 | -------------------------------------------------------------------------------- /include/qt_touch.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_SYNCVAR_OPERATIONS_H 2 | #define QT_SYNCVAR_OPERATIONS_H 3 | 4 | #include "qthread/qthread.h" 5 | 6 | void qthread_run_needed_task(syncvar_t *value); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /include/qt_visibility.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_VISIBILITY_H 2 | #define QT_VISIBILITY_H 3 | 4 | #if defined(_WIN32) || defined(__CYGWIN__) 5 | #warning Building on windows has never been tested 6 | #ifdef BUILDING_DLL 7 | #ifdef __GNUC__ 8 | #define API_FUNC __attribute__((dllexport)) 9 | #else 10 | #define API_FUNC \ 11 | __declspec(dllexport) // Note: actually gcc seems to also supports this 12 | // syntax. 13 | #endif 14 | #else 15 | #ifdef __GNUC__ 16 | #define API_FUNC __attribute__((dllimport)) 17 | #else 18 | #define API_FUNC \ 19 | __declspec(dllimport) // Note: actually gcc seems to also supports this 20 | // syntax. 21 | #endif 22 | #endif /* ifdef BUILDING_DLL */ 23 | #define INTERNAL 24 | #else /* if defined(_WIN32) || defined(__CYGWIN__) */ 25 | #if __GNUC__ >= 4 26 | #define API_FUNC __attribute__((visibility("default"))) 27 | #define INTERNAL __attribute__((visibility("hidden"))) 28 | #else 29 | #define API_FUNC 30 | #define INTERNAL 31 | #endif 32 | #endif /* if defined(_WIN32) || defined(__CYGWIN__) */ 33 | 34 | #endif /* ifndef QT_VISIBILITY_H */ 35 | /* vim:set expandtab: */ 36 | -------------------------------------------------------------------------------- /include/qthread/.gitignore: -------------------------------------------------------------------------------- 1 | common.h 2 | stamp-h2 3 | -------------------------------------------------------------------------------- /include/qthread/allpairs.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_ALLPAIRS_H 2 | #define QTHREAD_ALLPAIRS_H 3 | 4 | #include "macros.h" 5 | #include "qarray.h" 6 | 7 | Q_STARTCXX /* */ 8 | typedef void (*dist_f)(void const *unit1, void const *unit2); 9 | typedef void (*dist_out_f)(void const *unit1, 10 | void const *unit2, 11 | void *restrict outstore); 12 | 13 | void qt_allpairs(qarray const *array1, qarray const *array2, dist_f distfunc); 14 | void qt_allpairs_output(qarray const *array1, 15 | qarray const *array2, 16 | dist_out_f distfunc, 17 | void *restrict *restrict output, 18 | size_t outsize); 19 | 20 | Q_ENDCXX /* */ 21 | #endif // ifndef QTHREAD_ALLPAIRS_H 22 | /* vim:set expandtab: */ 23 | -------------------------------------------------------------------------------- /include/qthread/barrier.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_LOG_BARRIER_H 2 | #define QTHREAD_LOG_BARRIER_H 3 | 4 | #include "macros.h" 5 | #include "qthread.h" 6 | 7 | Q_STARTCXX 8 | 9 | /************************************************************/ 10 | /* Typedefs */ 11 | /************************************************************/ 12 | typedef enum { REGION_BARRIER, LOOP_BARRIER } qt_barrier_btype; 13 | 14 | typedef enum { UPLOCK, DOWNLOCK, BOTHLOCKS } qt_barrier_dtype; 15 | 16 | typedef struct qt_barrier_s qt_barrier_t; 17 | 18 | /************************************************************/ 19 | /* Functions */ 20 | /************************************************************/ 21 | qt_barrier_t *qt_barrier_create(size_t max_threads, qt_barrier_btype type); 22 | void qt_barrier_enter(qt_barrier_t *b); 23 | void qt_barrier_enter_id(qt_barrier_t *b, size_t id); 24 | void qt_barrier_destroy(qt_barrier_t *b); 25 | void qt_barrier_resize(qt_barrier_t *b, size_t size); 26 | 27 | /* debugging... */ 28 | void qt_barrier_dump(qt_barrier_t *b, qt_barrier_dtype dt); 29 | 30 | /* functions definded in qthread.c to support nested parallelism and barriers */ 31 | qt_barrier_t *qt_get_barrier(void); 32 | void qt_set_barrier(qt_barrier_t *); 33 | 34 | Q_ENDCXX 35 | 36 | #endif // ifndef QTHREAD_LOG_BARRIER_H 37 | /* vim:set expandtab: */ 38 | -------------------------------------------------------------------------------- /include/qthread/cacheline.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_CACHELINE_H 2 | #define QTHREAD_CACHELINE_H 3 | 4 | #include "macros.h" 5 | 6 | Q_STARTCXX /* */ 7 | int qthread_cacheline(void); 8 | Q_ENDCXX /* */ 9 | 10 | #endif // ifndef QTHREAD_CACHELINE_H 11 | /* vim:set expandtab: */ 12 | -------------------------------------------------------------------------------- /include/qthread/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_HASH_H 2 | #define QTHREAD_HASH_H 3 | 4 | #include "common.h" /* important configuration options */ 5 | #include "macros.h" 6 | #include "qthread.h" /* for uint64_t, uint8_t, and aligned_t types */ 7 | 8 | Q_STARTCXX /* */ 9 | 10 | #if (QTHREAD_BITS == 32) 11 | #define GOLDEN_RATIO 0x9e3779b9 12 | #else 13 | #define GOLDEN_RATIO 0x9e3779b97f4a7c13LL 14 | #endif 15 | 16 | uint64_t 17 | qt_hash64(uint64_t key); 18 | aligned_t qt_hash_bytes(void *key_ptr, size_t bytes, aligned_t state); 19 | 20 | Q_ENDCXX /* */ 21 | #endif // ifndef QTHREAD_HASH_H 22 | /* vim:set expandtab: */ 23 | -------------------------------------------------------------------------------- /include/qthread/io.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_IO_H 2 | #define QTHREAD_IO_H 3 | 4 | #include "macros.h" 5 | 6 | Q_STARTCXX 7 | void qt_begin_blocking_action(void); 8 | void qt_end_blocking_action(void); 9 | Q_ENDCXX 10 | 11 | #endif 12 | /* vim:set expandtab: */ 13 | -------------------------------------------------------------------------------- /include/qthread/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_MACROS_H 2 | #define QTHREAD_MACROS_H 3 | 4 | #ifdef __cplusplus 5 | #define Q_STARTCXX extern "C" { 6 | #define Q_ENDCXX } 7 | #else 8 | #define Q_STARTCXX 9 | #define Q_ENDCXX 10 | #endif 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/qthread/qdqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_QDQUEUE_H 2 | #define QTHREAD_QDQUEUE_H 3 | 4 | #include "macros.h" 5 | #include "qthread.h" 6 | 7 | Q_STARTCXX /* */ 8 | typedef struct qdqueue_s qdqueue_t; 9 | 10 | /* Create a new qdqueue */ 11 | qdqueue_t *qdqueue_create(void); 12 | 13 | /* destroy that queue */ 14 | int qdqueue_destroy(qdqueue_t *q); 15 | 16 | /* enqueue something in the queue */ 17 | int qdqueue_enqueue(qdqueue_t *q, void *elem); 18 | 19 | /* enqueue something in the queue at a given location */ 20 | int qdqueue_enqueue_there(qdqueue_t *q, 21 | void *elem, 22 | qthread_shepherd_id_t there); 23 | 24 | /* dequeue something from the queue (returns NULL for an empty queue) */ 25 | void *qdqueue_dequeue(qdqueue_t *q); 26 | 27 | /* returns 1 if the queue is empty, 0 otherwise */ 28 | int qdqueue_empty(qdqueue_t *q); 29 | 30 | Q_ENDCXX /* */ 31 | #endif // ifndef QTHREAD_QDQUEUE_H 32 | /* vim:set expandtab: */ 33 | -------------------------------------------------------------------------------- /include/qthread/qlfqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_QLFQUEUE_H 2 | #define QTHREAD_QLFQUEUE_H 3 | 4 | #include "macros.h" 5 | 6 | Q_STARTCXX /* */ 7 | 8 | typedef struct qlfqueue_s qlfqueue_t; 9 | 10 | /* Create a new qlfqueue */ 11 | qlfqueue_t *qlfqueue_create(void); 12 | 13 | /* destroy that queue */ 14 | int qlfqueue_destroy(qlfqueue_t *q); 15 | 16 | /* enqueue something in the queue */ 17 | int qlfqueue_enqueue(qlfqueue_t *q, void *elem); 18 | 19 | /* dequeue something from the queue (returns NULL for an empty queue) */ 20 | void *qlfqueue_dequeue(qlfqueue_t *q); 21 | 22 | /* returns 1 if the queue is empty, 0 otherwise */ 23 | int qlfqueue_empty(qlfqueue_t *q); 24 | 25 | Q_ENDCXX /* */ 26 | 27 | #endif // ifndef QTHREAD_QLFQUEUE_H 28 | /* vim:set expandtab: */ 29 | -------------------------------------------------------------------------------- /include/qthread/qpool.h: -------------------------------------------------------------------------------- 1 | #ifndef QPOOL_H 2 | #define QPOOL_H 3 | 4 | #include /* for size_t (according to C89) */ 5 | 6 | #include "macros.h" 7 | 8 | Q_STARTCXX /* */ 9 | 10 | typedef struct qt_mpool_s qpool; 11 | 12 | void *qpool_alloc(qpool *pool); 13 | 14 | void qpool_free(qpool *restrict pool, void *restrict mem); 15 | 16 | qpool *qpool_create(size_t const item_size); 17 | qpool *qpool_create_aligned(size_t const item_size, size_t const alignment); 18 | 19 | void qpool_destroy(qpool *pool); 20 | 21 | Q_ENDCXX /* */ 22 | 23 | #endif // ifndef QPOOL_H 24 | /* vim:set expandtab: */ 25 | -------------------------------------------------------------------------------- /include/qthread/qswsrqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_QSWSRQUEUE_H 2 | #define QTHREAD_QSWSRQUEUE_H 3 | 4 | #include 5 | 6 | #include "macros.h" 7 | 8 | Q_STARTCXX /* */ 9 | 10 | typedef struct qswsrqueue_s qswsrqueue_t; 11 | 12 | /* Create a new qswsrqueue */ 13 | qswsrqueue_t *qswsrqueue_create(size_t elements); 14 | 15 | /* destroy that queue */ 16 | int qswsrqueue_destroy(qswsrqueue_t *q); 17 | 18 | /* enqueue something in the queue if there is room */ 19 | int qswsrqueue_enqueue(qswsrqueue_t *q, void *elem); 20 | 21 | /* enqueue something in the queue */ 22 | int qswsrqueue_enqueue_blocking(qswsrqueue_t *q, void *elem); 23 | 24 | /* dequeue something from the queue (returns NULL for an empty queue) */ 25 | void *qswsrqueue_dequeue(qswsrqueue_t *q); 26 | 27 | /* dequeue something from the queue */ 28 | void *qswsrqueue_dequeue_blocking(qswsrqueue_t *q); 29 | 30 | /* returns 1 if the queue is empty, 0 otherwise */ 31 | int qswsrqueue_empty(qswsrqueue_t *q); 32 | 33 | Q_ENDCXX /* */ 34 | 35 | #endif // ifndef QTHREAD_QLFQUEUE_H 36 | /* vim:set expandtab: */ 37 | -------------------------------------------------------------------------------- /include/qthread/qt_syscalls.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_SYSCALLS_H 2 | #define QT_SYSCALLS_H 3 | 4 | #include /* for struct pollfd and nfds_t */ 5 | #include /* for struct rusage */ 6 | #include /* for fd_set */ 7 | #include 8 | #include 9 | 10 | #include "macros.h" 11 | 12 | Q_STARTCXX /* */ 13 | 14 | int qt_accept(int socket, 15 | struct sockaddr *restrict address, 16 | socklen_t *restrict address_len); 17 | int qt_connect(int socket, 18 | const struct sockaddr *address, 19 | socklen_t address_len); 20 | int qt_poll(struct pollfd fds[], nfds_t nfds, int timeout); 21 | ssize_t qt_pread(int filedes, void *buf, size_t nbyte, off_t offset); 22 | ssize_t qt_pwrite(int filedes, void const *buf, size_t nbyte, off_t offset); 23 | ssize_t qt_read(int filedes, void *buf, size_t nbyte); 24 | int qt_select(int nfds, 25 | fd_set *restrict readfds, 26 | fd_set *restrict writefds, 27 | fd_set *restrict errorfds, 28 | struct timeval *restrict timeout); 29 | int qt_system(char const *command); 30 | pid_t qt_wait4(pid_t pid, int *stat_loc, int options, struct rusage *rusage); 31 | ssize_t qt_write(int filedes, void const *buf, size_t nbyte); 32 | 33 | Q_ENDCXX /* */ 34 | 35 | #endif // ifndef QT_SYSCALLS_H 36 | /* vim:set expandtab: */ 37 | -------------------------------------------------------------------------------- /include/qthread/qthread.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _QTHREAD_HPP_ 2 | #define _QTHREAD_HPP_ 3 | 4 | #include "qthread.h" 5 | #include "syncvar.hpp" 6 | 7 | #endif // QTHREAD_HPP_ 8 | /* vim:set expandtab: */ 9 | -------------------------------------------------------------------------------- /include/qthread/qtimer.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_TIMER 2 | #define QTHREAD_TIMER 3 | 4 | #include "macros.h" 5 | 6 | Q_STARTCXX /* */ 7 | 8 | typedef struct qtimer_s *qtimer_t; 9 | 10 | unsigned long qtimer_fastrand(void); 11 | double qtimer_wtime(void); 12 | double qtimer_res(void); 13 | 14 | qtimer_t qtimer_create(void); 15 | void qtimer_destroy(qtimer_t); 16 | void qtimer_start(qtimer_t); 17 | void qtimer_stop(qtimer_t); 18 | double qtimer_secs(qtimer_t); 19 | 20 | Q_ENDCXX /* */ 21 | 22 | #endif // ifndef QTHREAD_TIMER 23 | /* vim:set expandtab: */ 24 | -------------------------------------------------------------------------------- /include/qthread/sinc.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_SINC_H 2 | #define QT_SINC_H 3 | 4 | #include 5 | 6 | #include "macros.h" 7 | #include "qthread.h" 8 | 9 | Q_STARTCXX /* */ 10 | 11 | typedef void (*qt_sinc_op_f)(void *tgt, void const *src); 12 | 13 | typedef struct qt_opaque_sinc_s { 14 | alignas(QTHREAD_ALIGNMENT_ALIGNED_T) uint8_t opaque_data[24]; 15 | } qt_sinc_t; 16 | 17 | void qt_sinc_init(qt_sinc_t *restrict sinc, 18 | size_t sizeof_value, 19 | void const *restrict initial_value, 20 | qt_sinc_op_f op, 21 | size_t expect); 22 | qt_sinc_t *qt_sinc_create(size_t sizeof_value, 23 | void const *initial_value, 24 | qt_sinc_op_f op, 25 | size_t expect); 26 | void qt_sinc_reset(qt_sinc_t *sinc, size_t expect); 27 | void qt_sinc_fini(qt_sinc_t *sinc); 28 | void qt_sinc_destroy(qt_sinc_t *sinc); 29 | void qt_sinc_expect(qt_sinc_t *sinc, size_t count); 30 | void *qt_sinc_tmpdata(qt_sinc_t *sinc); 31 | void qt_sinc_submit(qt_sinc_t *restrict sinc, void const *restrict value); 32 | void qt_sinc_wait(qt_sinc_t *restrict sinc, void *restrict target); 33 | 34 | Q_ENDCXX /* */ 35 | 36 | #endif // ifndef QT_SINC_H 37 | /* vim:set expandtab: */ 38 | -------------------------------------------------------------------------------- /include/qthread/tls.h: -------------------------------------------------------------------------------- 1 | #ifndef TLS_H 2 | #define TLS_H 3 | 4 | typedef void **qthread_key_t; 5 | 6 | int qthread_key_create(qthread_key_t *key, void (*destructor)(void *)); 7 | int qthread_key_delete(qthread_key_t key); 8 | void *qthread_getspecific(qthread_key_t key); 9 | int qthread_setspecific(qthread_key_t key, void const *value); 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /include/qthread/top/qthread.h: -------------------------------------------------------------------------------- 1 | 2 | #include "qthread/qthread.h" 3 | -------------------------------------------------------------------------------- /include/qthread/wavefront.h: -------------------------------------------------------------------------------- 1 | #ifndef QTHREAD_WAVEFRONT_H 2 | #define QTHREAD_WAVEFRONT_H 3 | 4 | #include "qarray.h" 5 | 6 | Q_STARTCXX /* */ 7 | typedef void (*wave_comp_f)(void const *restrict left, 8 | void const *restrict leftdown, 9 | void const *restrict down, 10 | void *restrict out); 11 | typedef void (*wave_f)(qarray *restrict left, qarray *restrict below, void **R); 12 | 13 | typedef struct qt_wavefront_lattice_s qt_wavefront_lattice; 14 | 15 | qt_wavefront_lattice *qt_wavefront(qarray *restrict const left, 16 | qarray *restrict const below, 17 | wave_comp_f func); 18 | void qt_wavefront_print_lattice(qt_wavefront_lattice const *const L); 19 | void qt_wavefront_destroy_lattice(qt_wavefront_lattice *const L); 20 | 21 | void qt_basic_wavefront(int *restrict const *const R, 22 | size_t cols, 23 | size_t rows, 24 | wave_comp_f func); 25 | 26 | Q_ENDCXX /* */ 27 | #endif // ifndef QTHREAD_WAVEFRONT_H 28 | /* vim:set expandtab: */ 29 | -------------------------------------------------------------------------------- /include/rose_sinc_barrier.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_SINC_BARRIER_H 2 | #define QT_SINC_BARRIER_H 3 | 4 | #include 5 | 6 | typedef struct qt_sinc_barrier_s { 7 | uint64_t count; 8 | qt_sinc_t *sinc_1; 9 | qt_sinc_t *sinc_2; 10 | qt_sinc_t *sinc_3; 11 | } qt_sinc_barrier_t; 12 | 13 | /* function calls for sinc based barrier -- allows barriers threads to be 14 | * throttled within barrier regions - akp*/ 15 | void API_FUNC qt_sinc_barrier_enter(qt_sinc_barrier_t *b); 16 | void qt_sinc_barrier_init(qt_sinc_barrier_t *restrict barrier, size_t expect); 17 | void qt_sinc_barrier_destroy(qt_sinc_barrier_t *restrict barrier); 18 | void qt_sinc_barrier_change(qt_sinc_barrier_t *restrict barrier, size_t expect); 19 | 20 | extern qt_sinc_barrier_t *sinc_barrier; /* global barrier declaration -- may be 21 | dead now that nesting works - akp */ 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/spr_innards.h: -------------------------------------------------------------------------------- 1 | #ifndef SPR_INNARDS_H 2 | #define SPR_INNARDS_H 3 | 4 | #include "qthread/sinc.h" 5 | 6 | /* Action ID Category Offsets */ 7 | enum { 8 | spr_non_action = 0, 9 | spr_internals_base = 1, /* Internal SPR actions */ 10 | spr_init_base = 64, /* User actions (via spr_init() call) */ 11 | }; 12 | 13 | typedef struct spr_get_s { 14 | qt_sinc_t *sinc; 15 | void *dest_addr; 16 | int32_t size; 17 | } spr_get_t; 18 | 19 | struct spr_put_handle_s { 20 | aligned_t feb; 21 | }; 22 | 23 | struct spr_get_handle_s { 24 | aligned_t feb; 25 | }; 26 | 27 | #endif /* SPR_INNARDS_H */ 28 | /* vim:set expandtab: */ 29 | -------------------------------------------------------------------------------- /man/htmlize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if ! type rman 2>&1 ; then 3 | echo "Please install rman" 4 | exit -1 5 | fi 6 | mkdir html 7 | for F in man3/*.3 ; do 8 | newfile="${F%.3}.html" 9 | newfile="html/${newfile#man3/}" 10 | rman -f html -r '%s.html' -S "$F" > "${newfile}" || (echo "$F" && break) 11 | done 12 | -------------------------------------------------------------------------------- /man/man3/qalloc_checkpoint.3: -------------------------------------------------------------------------------- 1 | .TH qalloc_checkpoint 3 "NOVEMBER 2006" libqthread "libqthread" 2 | .SH NAME 3 | .BR qalloc_checkpoint " \- locks an address, and may block" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void 8 | .br 9 | .B qalloc_checkpoint 10 | (void); 11 | .SH DESCRIPTION 12 | This function sync's the maps to disk. This can be done at any time, and is as 13 | efficient as 14 | .BR msync (). 15 | .SH "SEE ALSO" 16 | .BR qalloc_cleanup (3), 17 | .BR qalloc_free (3), 18 | .BR qalloc_loadmap (3), 19 | .BR qalloc_malloc (3), 20 | .BR msync (2) 21 | -------------------------------------------------------------------------------- /man/man3/qalloc_cleanup.3: -------------------------------------------------------------------------------- 1 | .TH qalloc_cleanup 3 "NOVEMBER 2006" libqthread "libqthread" 2 | .SH NAME 3 | .BR qalloc_cleanup " \- unmaps all memory maps" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void 8 | .br 9 | .B qalloc_cleanup 10 | (void); 11 | .SH DESCRIPTION 12 | This function performs a checkpoint, with 13 | .BR qalloc_checkpoint (), 14 | and then un-maps all of the currently mapped memory maps. 15 | .SH SEE ALSO 16 | .BR qalloc_checkpoint (3), 17 | .BR qalloc_free (3), 18 | .BR qalloc_loadmap (3), 19 | .BR qalloc_malloc (3) 20 | -------------------------------------------------------------------------------- /man/man3/qalloc_dynfree.3: -------------------------------------------------------------------------------- 1 | .so man3/qalloc_free.3 2 | -------------------------------------------------------------------------------- /man/man3/qalloc_dynmalloc.3: -------------------------------------------------------------------------------- 1 | .so man3/qalloc_malloc.3 2 | -------------------------------------------------------------------------------- /man/man3/qalloc_free.3: -------------------------------------------------------------------------------- 1 | .TH qalloc_free 3 "NOVEMBER 2006" libqthread "libqthread" 2 | .SH NAME 3 | .BR qalloc_free , 4 | .BR qalloc_dynfree , 5 | .B qalloc_statfree 6 | \- return an allocated block to the map 7 | .SH SYNOPSIS 8 | .B #include 9 | 10 | .I void 11 | .br 12 | .B qalloc_free 13 | .RI "(void *" block ", void *" map ); 14 | .PP 15 | .I void 16 | .br 17 | .B qalloc_statfree 18 | .RI "(void *" block ", struct mapinfo_s *" map ); 19 | .PP 20 | .I void 21 | .br 22 | .B qalloc_dynfree 23 | .RI "(void *" block ", struct dynmapinfo_s *" map ); 24 | .SH DESCRIPTION 25 | These are the deallocation functions. They return an allocated memory 26 | .I block 27 | to the specified qalloc 28 | .IR map . 29 | The 30 | .BR qalloc_free () 31 | function will use whichever of the other two functions is appropriate for the given 32 | .IR map . 33 | .SH SEE ALSO 34 | .BR qalloc_cleanup (3), 35 | .BR qalloc_checkpoint (3), 36 | .BR qalloc_loadmap (3), 37 | .BR qalloc_malloc (3) 38 | -------------------------------------------------------------------------------- /man/man3/qalloc_makedynmap.3: -------------------------------------------------------------------------------- 1 | .so man3/qalloc_loadmap.3 2 | -------------------------------------------------------------------------------- /man/man3/qalloc_makestatmap.3: -------------------------------------------------------------------------------- 1 | .so man3/qalloc_loadmap.3 2 | -------------------------------------------------------------------------------- /man/man3/qalloc_malloc.3: -------------------------------------------------------------------------------- 1 | .TH qalloc_malloc 3 "NOVEMBER 2006" libqthread "libqthread" 2 | .SH NAME 3 | .BR qalloc_malloc , 4 | .BR qalloc_statmalloc , 5 | .B qalloc_dynmalloc 6 | \- allocates memory from the specified map 7 | .SH SYNOPSIS 8 | .B #include 9 | 10 | .I void * 11 | .br 12 | .B qalloc_malloc 13 | .RI "(void *" map ", size_t " size ); 14 | .PP 15 | .I void * 16 | .br 17 | .B qalloc_statmalloc 18 | .RI "(struct mapinfo_s *" map ); 19 | .PP 20 | .I void * 21 | .br 22 | .B qalloc_dynmalloc 23 | .RI "(struct dynmapinfo_s *" map ", size_t " size ); 24 | .SH DESCRIPTION 25 | These are the allocation functions. They return a pointer to an allocated 26 | memory block from the specified qalloc 27 | .IR map . 28 | The 29 | .BR qalloc_statmalloc () 30 | function only needs a pointer to the 31 | .I map 32 | itself, as the size of the returned block is the same for all allocations from 33 | that map. 34 | .BR qalloc_dynmalloc () 35 | on the other hand also takes a 36 | .I size 37 | argument, since by definition, a dynamic map allows for any size allocation. 38 | .BR qalloc_malloc () 39 | will use whichever of the other two functions is appropriate for the map it is 40 | passed; however, if the map is a static map, the 41 | .I size 42 | argument is ignored. 43 | .SH SEE ALSO 44 | .BR qalloc_cleanup (3), 45 | .BR qalloc_checkpoint (3), 46 | .BR qalloc_free (3), 47 | .BR qalloc_loadmap (3) 48 | -------------------------------------------------------------------------------- /man/man3/qalloc_statfree.3: -------------------------------------------------------------------------------- 1 | .so man3/qalloc_free.3 2 | -------------------------------------------------------------------------------- /man/man3/qalloc_statmalloc.3: -------------------------------------------------------------------------------- 1 | .so man3/qalloc_malloc.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_create_configured.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_create_tight.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qarray_destroy 3 "MAY 2009" libqthread "libqthread" 2 | .SH NAME 3 | .BR qarray_destroy " \- deallocate a distributed array" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void 8 | .br 9 | .B qarray_destroy 10 | .RI "(qarray *" a ); 11 | .SH DESCRIPTION 12 | This function deallocates a qarray safely, and updates all internal bookkeeping 13 | counters. 14 | .SH SEE ALSO 15 | .BR qarray_create (3), 16 | .BR qarray_iter (3), 17 | .BR qarray_shepof (3), 18 | .BR qarray_elem (3) 19 | -------------------------------------------------------------------------------- /man/man3/qarray_dist_like.3: -------------------------------------------------------------------------------- 1 | .TH qarray_dist_like 3 "JUNE 2010" libqthread "libqthread" 2 | .SH NAME 3 | .B qarray_dist_like 4 | \- redistribute a qarray to match another qarray 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qarray_dist_like 11 | .RI "(const qarray *" ref", qarray *" mod ); 12 | .SH DESCRIPTION 13 | This function modifies the qarray 14 | .I mod 15 | to match the distribution of qarray 16 | .IR ref . 17 | These functions manipulate or report the shepherd to which the 18 | .I index 19 | elementof the 20 | .I array 21 | qarray is assigned. Note that not all types of qarray can be made to match all 22 | other types of qarray; if the qarrays cannot be distributed similarly, the 23 | input qarrays are unmodified. 24 | .SH SEE ALSO 25 | .BR qarray_create (3), 26 | .BR qarray_destroy (3), 27 | .BR qarray_iter (3), 28 | .BR qarray_elem (3) 29 | -------------------------------------------------------------------------------- /man/man3/qarray_elem.3: -------------------------------------------------------------------------------- 1 | .TH qarray_elem 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qarray_elem " \- return a pointer to a distributed array element" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void * 8 | .br 9 | .B qarray_elem 10 | .RI "(const qarray * " array ", const size_t " index ); 11 | .PP 12 | .I void * 13 | .br 14 | .B qarray_elem_nomigrate 15 | .RI "(const qarray * " array ", const size_t " index ); 16 | .PP 17 | .I void * 18 | .br 19 | .B qarray_elem_migrate 20 | .RI "(const qarray * " array ", const size_t " index ); 21 | .SH DESCRIPTION 22 | These functions return a pointer to the 23 | .I index 24 | element of the 25 | .I array 26 | distributed array. The 27 | .BR qarray_elem_migrate () 28 | function will additionally migrate the calling thread to the shepherd of the 29 | specified element. 30 | .SH SEE ALSO 31 | .BR qarray_create (3), 32 | .BR qarray_destroy (3), 33 | .BR qarray_iter (3), 34 | .BR qarray_shepof (3) 35 | -------------------------------------------------------------------------------- /man/man3/qarray_elem_migrate.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_elem.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_elem_nomigrate.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_elem.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_iter_constloop.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_iter.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_iter_loop.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_iter.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_iter_loop_nb.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_iter_loop.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_iter_loopaccum.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_iter.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_set_shepof.3: -------------------------------------------------------------------------------- 1 | .so man3/qarray_shepof.3 2 | -------------------------------------------------------------------------------- /man/man3/qarray_shepof.3: -------------------------------------------------------------------------------- 1 | .TH qarray_shepof 3 "MAY 2009" libqthread "libqthread" 2 | .SH NAME 3 | .BR qarray_shepof , 4 | .B qarray_set_shepof 5 | \- locate a distributed array element 6 | .SH SYNOPSIS 7 | .B #include 8 | 9 | .I qthread_shepherd_id_t 10 | .br 11 | .B qarray_shepof 12 | .RI "(const qarray *" array ", const size_t " index ); 13 | .PP 14 | .I void 15 | .br 16 | .B qarray_set_shepof 17 | .RI "(qarray *" array ", const size_t " index , 18 | .ti +19 19 | .RI "qthread_shepherd_id_t " shep ); 20 | .SH DESCRIPTION 21 | These functions manipulate or report the shepherd to which the 22 | .I index 23 | elementof the 24 | .I array 25 | qarray is assigned. 26 | .SH SEE ALSO 27 | .BR qarray_create (3), 28 | .BR qarray_destroy (3), 29 | .BR qarray_iter (3), 30 | .BR qarray_elem (3) 31 | -------------------------------------------------------------------------------- /man/man3/qdqueue_create.3: -------------------------------------------------------------------------------- 1 | .TH qdqueue_create 3 "OCTOBER 2009" libqthread "libqthread" 2 | .SH NAME 3 | .BR qdqueue_create " \- allocate a distributed queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I qdqueue_t * 8 | .br 9 | .B qdqueue_create 10 | (void); 11 | .SH DESCRIPTION 12 | This function initializes a qdqueue distributed queue object. This distributed 13 | queue is locality aware, and as such prioritizes "nearby" data over the 14 | globally oldest data. It provides an end-to-end ordering guarantee: elements 15 | enqueued from any given location may not be consumed out of order by any other 16 | single location. 17 | .SH SEE ALSO 18 | .BR qlfqueue_create (3), 19 | .BR qdqueue_destroy (3), 20 | .BR qdqueue_enqueue (3), 21 | .BR qdqueue_dequeue (3), 22 | .BR qdqueue_empty (3) 23 | -------------------------------------------------------------------------------- /man/man3/qdqueue_dequeue.3: -------------------------------------------------------------------------------- 1 | .TH qdqueue_dequeue 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qdqueue_dequeue " \- remove an element from a distributed queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void * 8 | .br 9 | .B qdqueue_dequeue 10 | .RI "(qdqueue_t *" q ); 11 | .SH DESCRIPTION 12 | This function removes an element from the distributed queue and returns a pointer to it. 13 | .SH RETURN VALUE 14 | The return value is one of the pointers that was enqueued in the queue. 15 | .SH SEE ALSO 16 | .BR qlfqueue_dequeue (3), 17 | .BR qdqueue_create (3), 18 | .BR qdqueue_enqueue (3), 19 | .BR qdqueue_destroy (3), 20 | .BR qdqueue_empty (3) 21 | -------------------------------------------------------------------------------- /man/man3/qdqueue_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qdqueue_destroy 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qdqueue_destroy " \- deallocate a distributed queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void 8 | .br 9 | .B qdqueue_destroy 10 | .RI "(qdqueue_t *" q ); 11 | .SH DESCRIPTION 12 | This function deallocates a qdqueue safely. 13 | .SH SEE ALSO 14 | .BR qlfqueue_destroy (3), 15 | .BR qdqueue_create (3), 16 | .BR qdqueue_enqueue (3), 17 | .BR qdqueue_dequeue (3), 18 | .BR qdqueue_empty (3) 19 | -------------------------------------------------------------------------------- /man/man3/qdqueue_empty.3: -------------------------------------------------------------------------------- 1 | .TH qdqueue_empty 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qdqueue_empty " \- test whether a distributed queue is empty" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I int 8 | .br 9 | .B qdqueue_empty 10 | .RI "(qdqueue_t *" q ); 11 | .SH DESCRIPTION 12 | This function checks whether the given qdqueue is empty. 13 | .SH RETURN VALUE 14 | The return value will be 1 if the queue is empty, or 0 otherwise. 15 | .SH SEE ALSO 16 | .BR qlfqueue_empty (3), 17 | .BR qdqueue_create (3), 18 | .BR qdqueue_enqueue (3), 19 | .BR qdqueue_dequeue (3), 20 | .BR qdqueue_destroy (3) 21 | -------------------------------------------------------------------------------- /man/man3/qdqueue_enqueue.3: -------------------------------------------------------------------------------- 1 | .TH qdqueue_enqueue 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qdqueue_enqueue " \- append an element to a distributed queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I int 8 | .br 9 | .B qdqueue_enqueue 10 | .RI "(qdqueue_t *" q ", void *" elem ); 11 | .PP 12 | .I int 13 | .br 14 | .B qdqueue_enqueue_there 15 | .RI "(qdqueue_t *" q ", void *" elem , 16 | .ti +23 17 | .RI "qthread_shepherd_id_t " there ); 18 | .SH DESCRIPTION 19 | These two functions append elements to distributed queues. The 20 | .BR qdqueue_enqueue () 21 | function is equivalent to 22 | .BR qdqueue_enqueue_there () 23 | when the 24 | .I there 25 | location is the current shepherd (e.g. the result of 26 | .BR qthread_shep (NULL)). 27 | .SH RETURN VALUE 28 | The return value will be 0 for success, or will indicate an error. 29 | .SH ERROR CODES 30 | Possible error codes are: 31 | .TP 4 32 | QTHREAD_BADARGS 33 | This indicates that one of the input arguments was null. 34 | .SH SEE ALSO 35 | .BR qlfqueue_enqueue (3), 36 | .BR qdqueue_create (3), 37 | .BR qdqueue_enqueue (3), 38 | .BR qdqueue_dequeue (3), 39 | .BR qdqueue_empty (3) 40 | -------------------------------------------------------------------------------- /man/man3/qdqueue_enqueue_there.3: -------------------------------------------------------------------------------- 1 | .so man3/qdqueue_enqueue.3 2 | -------------------------------------------------------------------------------- /man/man3/qlfqueue_create.3: -------------------------------------------------------------------------------- 1 | .TH qlfqueue_create 3 "OCTOBER 2009" libqthread "libqthread" 2 | .SH NAME 3 | .BR qlfqueue_create " \- allocate a lock-free queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I qlfqueue_t * 8 | .br 9 | .B qlfqueue_create 10 | (void); 11 | .SH DESCRIPTION 12 | This function initializes a qlfqueue lock-free queue object. This queue provides global ordering, using the 13 | .BR qthread_cas_ptr () 14 | functions. 15 | .SH SEE ALSO 16 | .BR qdqueue_create (3), 17 | .BR qlfqueue_destroy (3), 18 | .BR qlfqueue_enqueue (3), 19 | .BR qlfqueue_dequeue (3), 20 | .BR qlfqueue_empty (3) 21 | -------------------------------------------------------------------------------- /man/man3/qlfqueue_dequeue.3: -------------------------------------------------------------------------------- 1 | .TH qlfqueue_dequeue 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qlfqueue_dequeue " \- remove an element from a lock-free queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void * 8 | .br 9 | .B qlfqueue_dequeue 10 | .RI "(qlfqueue_t *" q ); 11 | .SH DESCRIPTION 12 | This function removes an element from the queue and returns a pointer to it. 13 | .SH RETURN VALUE 14 | The return value is one of the pointers that was enqueued in the queue. 15 | .SH SEE ALSO 16 | .BR qdqueue_dequeue (3), 17 | .BR qlfqueue_create (3), 18 | .BR qlfqueue_enqueue (3), 19 | .BR qlfqueue_destroy (3), 20 | .BR qlfqueue_empty (3) 21 | -------------------------------------------------------------------------------- /man/man3/qlfqueue_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qlfqueue_destroy 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qlfqueue_destroy " \- deallocate a lock-free queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void 8 | .br 9 | .B qlfqueue_destroy 10 | .RI "(qlfqueue_t *" q ); 11 | .SH DESCRIPTION 12 | This function deallocates a qlfqueue safely. 13 | .SH SEE ALSO 14 | .BR qdqueue_destroy (3), 15 | .BR qlfqueue_create (3), 16 | .BR qlfqueue_enqueue (3), 17 | .BR qlfqueue_dequeue (3), 18 | .BR qlfqueue_empty (3) 19 | -------------------------------------------------------------------------------- /man/man3/qlfqueue_empty.3: -------------------------------------------------------------------------------- 1 | .TH qlfqueue_empty 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qlfqueue_empty " \- test whether a lock-free queue is empty" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I int 8 | .br 9 | .B qlfqueue_empty 10 | .RI "(qlfqueue_t *" q ); 11 | .SH DESCRIPTION 12 | This function checks whether the given qlfqueue is empty. 13 | .SH RETURN VALUE 14 | The return value will be 1 if the queue is empty, or 0 otherwise. 15 | .SH SEE ALSO 16 | .BR qdqueue_empty (3), 17 | .BR qlfqueue_create (3), 18 | .BR qlfqueue_enqueue (3), 19 | .BR qlfqueue_dequeue (3), 20 | .BR qlfqueue_destroy (3) 21 | -------------------------------------------------------------------------------- /man/man3/qlfqueue_enqueue.3: -------------------------------------------------------------------------------- 1 | .TH qlfqueue_enqueue 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qlfqueue_enqueue " \- append an element to a lock-free queue" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I int 8 | .br 9 | .B qlfqueue_enqueue 10 | .RI "(qlfqueue_t *" q ", void *" elem ); 11 | .SH DESCRIPTION 12 | This function appends elements to lock-free queues. 13 | .SH RETURN VALUE 14 | The return value will be 0 for success, or will indicate an error. 15 | .SH ERROR CODES 16 | Possible error codes are: 17 | .TP 4 18 | QTHREAD_BADARGS 19 | This indicates that one of the input arguments was null. 20 | .SH SEE ALSO 21 | .BR qdqueue_enqueue (3), 22 | .BR qlfqueue_create (3), 23 | .BR qlfqueue_enqueue (3), 24 | .BR qlfqueue_dequeue (3), 25 | .BR qlfqueue_empty (3) 26 | -------------------------------------------------------------------------------- /man/man3/qpool_alloc.3: -------------------------------------------------------------------------------- 1 | .TH qpool_alloc 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qpool_alloc " \- allocate memory from a distributed memory pool" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void * 8 | .br 9 | .B qpool_alloc 10 | .RI "(qpool *" pool ); 11 | .SH DESCRIPTION 12 | This function pulls a memory block from the specified memory pool. The memory 13 | may not be local, but will be from nearby if local memory cannot be found. 14 | .SH SEE ALSO 15 | .BR qpool_destroy (3), 16 | .BR qpool_create (3), 17 | .BR qpool_free (3) 18 | -------------------------------------------------------------------------------- /man/man3/qpool_create.3: -------------------------------------------------------------------------------- 1 | .TH qpool_create 3 "MAY 2009" libqthread "libqthread" 2 | .SH NAME 3 | .BR qpool_create " \- allocate a distributed memory pool" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I qpool * 8 | .br 9 | .B qpool_create 10 | .RI "(const size_t " item_size ); 11 | .PP 12 | .I qpool * 13 | .br 14 | .B qpool_create_aligned 15 | .RI "(const size_t " item_size ", const size_t " alignment ); 16 | .SH DESCRIPTION 17 | These functions initialize qpool distributed memory pools. The 18 | .BR qpool_create_aligned () 19 | function allows the alignment to be specified, such that all allocated elements 20 | will align along specific alignment boundaries. The 21 | .I alignment 22 | value is expected to be a power of two. 23 | .SH SEE ALSO 24 | .BR qpool_destroy (3), 25 | .BR qpool_alloc (3), 26 | .BR qpool_free (3) 27 | -------------------------------------------------------------------------------- /man/man3/qpool_create_aligned.3: -------------------------------------------------------------------------------- 1 | .so man3/qpool_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qpool_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qpool_destroy 3 "MAY 2009" libqthread "libqthread" 2 | .SH NAME 3 | .BR qpool_destroy " \- deallocate a distributed memory pool" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void 8 | .br 9 | .B qpool_destroy 10 | .RI "(qpool *" pool ); 11 | .SH DESCRIPTION 12 | This function deallocates the specified distributed memory pool, and all memory 13 | associated with that pool (even if it had not yet been returned to the pool). 14 | .SH SEE ALSO 15 | .BR qpool_create (3), 16 | .BR qpool_alloc (3), 17 | .BR qpool_free (3) 18 | -------------------------------------------------------------------------------- /man/man3/qpool_free.3: -------------------------------------------------------------------------------- 1 | .TH qpool_free 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qpool_free " \- return a memory block to its distributed memory pool" 4 | .SH SYNOPSIS 5 | .B #include 6 | 7 | .I void 8 | .br 9 | .B qpool_free 10 | .RI "(qpool *restrict " pool ", void *restrict " mem ); 11 | .SH DESCRIPTION 12 | This function returns a block of memory 13 | .RI ( mem ) 14 | to its distributed memory pool 15 | .RI ( pool ). 16 | This memory must have originated in that pool. 17 | .SH SEE ALSO 18 | .BR qpool_destroy (3), 19 | .BR qpool_alloc (3), 20 | .BR qpool_create (3) 21 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_delete.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_delete 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_delete 4 | \- remove a key/value pair from the dictionary 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void * 9 | .br 10 | .B qt_dictionary_delete 11 | .RI "(qt_dictionary *" dict , 12 | .br 13 | .ti +22 14 | .RI "void *" key ); 15 | 16 | .SH DESCRIPTION 17 | This function removes a key/value pair, identified by the 18 | .IR key , 19 | from the dictionary data structure 20 | .IR dict . 21 | .SH RETURN VALUES 22 | Returns a pointer to the value associated with the 23 | .IR key , 24 | if the key was present in the dictionary, and NULL otherwise. 25 | .SH SEE ALSO 26 | .BR qt_dictionary_create (3), 27 | .BR qt_dictionary_destroy (3), 28 | .BR qt_dictionary_end (3), 29 | .BR qt_dictionary_get (3), 30 | .BR qt_dictionary_iterator_copy (3), 31 | .BR qt_dictionary_iterator_create (3), 32 | .BR qt_dictionary_iterator_destroy (3), 33 | .BR qt_dictionary_iterator_equals (3), 34 | .BR qt_dictionary_iterator_get (3), 35 | .BR qt_dictionary_iterator_next (3), 36 | .BR qt_dictionary_put (3), 37 | .BR qt_dictionary_put_if_absent (3) 38 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_destroy 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_destroy 4 | \- deallocate a concurrent dictionary 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_dictionary_destroy 11 | .RI "(qt_dictionary *" d ); 12 | 13 | .SH DESCRIPTION 14 | This function deallocates the dictionary data structure 15 | .IR d . The embedded tag cleanup function will be called for all tags remaining in the dictionary. 16 | .SH SEE ALSO 17 | .BR qt_dictionary_create (3), 18 | .BR qt_dictionary_delete (3), 19 | .BR qt_dictionary_end (3), 20 | .BR qt_dictionary_get (3), 21 | .BR qt_dictionary_iterator_copy (3), 22 | .BR qt_dictionary_iterator_create (3), 23 | .BR qt_dictionary_iterator_destroy (3), 24 | .BR qt_dictionary_iterator_equals (3), 25 | .BR qt_dictionary_iterator_get (3), 26 | .BR qt_dictionary_iterator_next (3), 27 | .BR qt_dictionary_put (3), 28 | .BR qt_dictionary_put_if_absent (3) 29 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_end.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_end 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_end 4 | \- create an iterator pointing to the end of the dictionary 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qt_dictionary_iterator * 9 | .br 10 | .B qt_dictionary_end 11 | .RI "(qt_dictionary *" dict ); 12 | 13 | .SH DESCRIPTION 14 | This function creates a new iterator on the dictionary 15 | .IR dict , 16 | pointing to the item past the end of the list (which is NULL). 17 | .SH RETURN VALUES 18 | Returns an initialized qt_dictionary_iterator object, or NULL if there was some kind of error. 19 | .SH SEE ALSO 20 | .BR qt_dictionary_create (3), 21 | .BR qt_dictionary_delete (3), 22 | .BR qt_dictionary_destroy (3), 23 | .BR qt_dictionary_get (3), 24 | .BR qt_dictionary_iterator_copy (3), 25 | .BR qt_dictionary_iterator_create (3), 26 | .BR qt_dictionary_iterator_destroy (3), 27 | .BR qt_dictionary_iterator_equals (3), 28 | .BR qt_dictionary_iterator_get (3), 29 | .BR qt_dictionary_iterator_next (3), 30 | .BR qt_dictionary_put (3), 31 | .BR qt_dictionary_put_if_absent (3) 32 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_get.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_get 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_get 4 | \- retrieve a value from the dictionary 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qt_dictionary * 9 | .br 10 | .B qt_dictionary_get 11 | .RI "(qt_dictionary *" dict , 12 | .br 13 | .ti +19 14 | .RI "void *" key ); 15 | 16 | .SH DESCRIPTION 17 | This function retrieves the value stored in the dictionary that is associated with the specified 18 | .IR key . 19 | .SH RETURN VALUES 20 | Returns the associated item if the 21 | .I key 22 | was present in the dictionary, or NULL otherwise. 23 | .SH SEE ALSO 24 | .BR qt_dictionary_create (3), 25 | .BR qt_dictionary_delete (3), 26 | .BR qt_dictionary_destroy (3), 27 | .BR qt_dictionary_end (3), 28 | .BR qt_dictionary_iterator_copy (3), 29 | .BR qt_dictionary_iterator_create (3), 30 | .BR qt_dictionary_iterator_destroy (3), 31 | .BR qt_dictionary_iterator_equals (3), 32 | .BR qt_dictionary_iterator_get (3), 33 | .BR qt_dictionary_iterator_next (3), 34 | .BR qt_dictionary_put (3), 35 | .BR qt_dictionary_put_if_absent (3) 36 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_iterator_copy.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_iterator_copy 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_iterator_copy 4 | \- duplicate an iterator 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qt_dictionary_iterator * 9 | .br 10 | .B qt_dictionary_iterator_copy 11 | .RI "(qt_dictionary_iterator *" input ); 12 | 13 | .SH DESCRIPTION 14 | This function allocates a new iterator and makes it a duplicate of the iterator specifies as 15 | .IR input . 16 | .SH RETURN VALUES 17 | Returns an initialized qt_dictionary_iterator object, or NULL if something went wrong. 18 | .SH SEE ALSO 19 | .BR qt_dictionary_create (3), 20 | .BR qt_dictionary_delete (3), 21 | .BR qt_dictionary_destroy (3), 22 | .BR qt_dictionary_end (3), 23 | .BR qt_dictionary_get (3), 24 | .BR qt_dictionary_iterator_create (3), 25 | .BR qt_dictionary_iterator_destroy (3), 26 | .BR qt_dictionary_iterator_equals (3), 27 | .BR qt_dictionary_iterator_get (3), 28 | .BR qt_dictionary_iterator_next (3), 29 | .BR qt_dictionary_put (3), 30 | .BR qt_dictionary_put_if_absent (3) 31 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_iterator_create.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_iterator_create 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_iterator_create 4 | \- allocate a concurrent dictionary iterator 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qt_dictionary_iterator * 9 | .br 10 | .B qt_dictionary_iterator_create 11 | .RI "(qt_dictionary *" dict ); 12 | 13 | .SH DESCRIPTION 14 | This function creates a dictionary iterator. The iterator points to the first element of the dictionary 15 | .IR dict . 16 | .SH RETURN VALUES 17 | Returns an initialized qt_dictionary_iterator object, or NULL if something went wrong. 18 | .SH SEE ALSO 19 | .BR qt_dictionary_create (3), 20 | .BR qt_dictionary_delete (3), 21 | .BR qt_dictionary_destroy (3), 22 | .BR qt_dictionary_end (3), 23 | .BR qt_dictionary_get (3), 24 | .BR qt_dictionary_iterator_copy (3), 25 | .BR qt_dictionary_iterator_destroy (3), 26 | .BR qt_dictionary_iterator_equals (3), 27 | .BR qt_dictionary_iterator_get (3), 28 | .BR qt_dictionary_iterator_next (3), 29 | .BR qt_dictionary_put (3), 30 | .BR qt_dictionary_put_if_absent (3) 31 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_iterator_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_iterator_destroy 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_iterator_destroy 4 | \- deallocate a qt_dictionary_iterator 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_dictionary_iterator_destroy 11 | .RI "(qt_dictionary_iterator *" iter ); 12 | 13 | .SH DESCRIPTION 14 | This function destroys the iterator object specified by 15 | .IR iter . 16 | .SH SEE ALSO 17 | .BR qt_dictionary_create (3), 18 | .BR qt_dictionary_delete (3), 19 | .BR qt_dictionary_destroy (3), 20 | .BR qt_dictionary_end (3), 21 | .BR qt_dictionary_get (3), 22 | .BR qt_dictionary_iterator_copy (3), 23 | .BR qt_dictionary_iterator_create (3), 24 | .BR qt_dictionary_iterator_equals (3), 25 | .BR qt_dictionary_iterator_get (3), 26 | .BR qt_dictionary_iterator_next (3), 27 | .BR qt_dictionary_put (3), 28 | .BR qt_dictionary_put_if_absent (3) 29 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_iterator_equals.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_iterator_equals 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_iterator_equals 4 | \- compare two iterators 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qt_dictionary_iterator_equals 11 | .RI "(qt_dictionary_iterator *" a , 12 | .br 13 | .ti +31 14 | .RI "qt_dictionary_iterator *" b ); 15 | 16 | .SH DESCRIPTION 17 | This function compares two iterators to test for equality. To be equal, they must both be associated with the same dictionary and must indicate the same positions within the dictionary. 18 | .SH RETURN VALUES 19 | Returns the value one if the iterators are equal, and zero otherwise. 20 | .SH SEE ALSO 21 | .BR qt_dictionary_create (3), 22 | .BR qt_dictionary_delete (3), 23 | .BR qt_dictionary_destroy (3), 24 | .BR qt_dictionary_end (3), 25 | .BR qt_dictionary_get (3), 26 | .BR qt_dictionary_iterator_copy (3), 27 | .BR qt_dictionary_iterator_create (3), 28 | .BR qt_dictionary_iterator_destroy (3), 29 | .BR qt_dictionary_iterator_get (3), 30 | .BR qt_dictionary_iterator_next (3), 31 | .BR qt_dictionary_put (3), 32 | .BR qt_dictionary_put_if_absent (3) 33 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_iterator_get.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_iterator_get 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_iterator_get 4 | \- retrieves the indicated entry in the dictionary 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I list_entry * 9 | .br 10 | .B qt_dictionary_iterator_get 11 | .RI "(const qt_dictionary_iterator *" iter ); 12 | 13 | .SH DESCRIPTION 14 | This function retrieves the entry indicated by the iterator 15 | .IR iter . 16 | .SH RETURN VALUES 17 | Returns a key/value pair, if there is one. 18 | In racy concurrent situations, if the item indicated by the iterator was 19 | deleted from the dictionary, multiple results may happen. The next element in 20 | the dictionary may be returned, or NULL may be returned, OR an error may be 21 | returned. However, it may not crash. 22 | .SH SEE ALSO 23 | .BR qt_dictionary_create (3), 24 | .BR qt_dictionary_delete (3), 25 | .BR qt_dictionary_destroy (3), 26 | .BR qt_dictionary_end (3), 27 | .BR qt_dictionary_get (3), 28 | .BR qt_dictionary_iterator_copy (3), 29 | .BR qt_dictionary_iterator_create (3), 30 | .BR qt_dictionary_iterator_destroy (3), 31 | .BR qt_dictionary_iterator_equals (3), 32 | .BR qt_dictionary_iterator_next (3), 33 | .BR qt_dictionary_put (3), 34 | .BR qt_dictionary_put_if_absent (3) 35 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_iterator_next.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_iterator_next 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_iterator_next 4 | \- retrieve the current value and advance the iterator 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I list_entry * 9 | .br 10 | .B qt_dictionary_iterator_next 11 | .RI "(qt_dictionary_iterator *" iter ); 12 | 13 | .SH DESCRIPTION 14 | This function advances the iterator and retrieves the next entry. The rules governing entry retrieval are the same as for 15 | .BR qt_dictionary_iterator_get (). 16 | .SH RETURN VALUES 17 | Returns the entry that the iterator points to after advancing. 18 | In racy concurrent situations, if the item indicated by the iterator was 19 | deleted from the dictionary, multiple results may happen. The next element in 20 | the dictionary may be returned, or NULL may be returned, OR an error may be 21 | returned. However, it may not crash. 22 | .SH SEE ALSO 23 | .BR qt_dictionary_create (3), 24 | .BR qt_dictionary_delete (3), 25 | .BR qt_dictionary_destroy (3), 26 | .BR qt_dictionary_end (3), 27 | .BR qt_dictionary_get (3), 28 | .BR qt_dictionary_iterator_copy (3), 29 | .BR qt_dictionary_iterator_create (3), 30 | .BR qt_dictionary_iterator_destroy (3), 31 | .BR qt_dictionary_iterator_equals (3), 32 | .BR qt_dictionary_iterator_get (3), 33 | .BR qt_dictionary_put (3), 34 | .BR qt_dictionary_put_if_absent (3) 35 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_put.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_put 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_put 4 | \- insert a key/value pair into a dictionary 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void * 9 | .br 10 | .B qt_dictionary_put 11 | .RI "(qt_dictionary *" dict , 12 | .br 13 | .ti +19 14 | .RI "void *" key , 15 | .br 16 | .ti +19 17 | .RI "void *" value ); 18 | 19 | .SH DESCRIPTION 20 | This function inserts a key/value pair, consisting of the 21 | .I key 22 | and 23 | .I value 24 | specified, into the dictionary 25 | .IR dict . 26 | If the 27 | .I key 28 | already exists within the dictionary, the value associated with it is replaced by 29 | .IR value . 30 | .SH RETURN VALUES 31 | Returns the address of the item in the dictionary after the put or NULL if the insert failed. 32 | .SH SEE ALSO 33 | .BR qt_dictionary_create (3), 34 | .BR qt_dictionary_delete (3), 35 | .BR qt_dictionary_destroy (3), 36 | .BR qt_dictionary_end (3), 37 | .BR qt_dictionary_get (3), 38 | .BR qt_dictionary_iterator_copy (3), 39 | .BR qt_dictionary_iterator_create (3), 40 | .BR qt_dictionary_iterator_destroy (3), 41 | .BR qt_dictionary_iterator_equals (3), 42 | .BR qt_dictionary_iterator_get (3), 43 | .BR qt_dictionary_iterator_next (3), 44 | .BR qt_dictionary_put_if_absent (3) 45 | -------------------------------------------------------------------------------- /man/man3/qt_dictionary_put_if_absent.3: -------------------------------------------------------------------------------- 1 | .TH qt_dictionary_put_if_absent 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_dictionary_put_if_absent 4 | \- insert a key/value pair into a dictionary 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void * 9 | .br 10 | .B qt_dictionary_put_if_absent 11 | .RI "(qt_dictionary *" dict , 12 | .br 13 | .ti +29 14 | .RI "void *" key , 15 | .br 16 | .ti +29 17 | .RI "void *" value ); 18 | 19 | .SH DESCRIPTION 20 | This function inserts a key/value pair, consisting of the 21 | .I key 22 | and 23 | .I value 24 | specified, into the dictionary 25 | .IR dict . 26 | The insertion will fail if the 27 | .I key 28 | is already present in the dictionary. 29 | .SH RETURN VALUES 30 | Returns the address of the item in the dictionary after the put or NULL if the insert failed. 31 | .SH SEE ALSO 32 | .BR qt_dictionary_create (3), 33 | .BR qt_dictionary_delete (3), 34 | .BR qt_dictionary_destroy (3), 35 | .BR qt_dictionary_end (3), 36 | .BR qt_dictionary_get (3), 37 | .BR qt_dictionary_iterator_copy (3), 38 | .BR qt_dictionary_iterator_create (3), 39 | .BR qt_dictionary_iterator_destroy (3), 40 | .BR qt_dictionary_iterator_equals (3), 41 | .BR qt_dictionary_iterator_get (3), 42 | .BR qt_dictionary_iterator_next (3), 43 | .BR qt_dictionary_put (3) 44 | -------------------------------------------------------------------------------- /man/man3/qt_end_blocking_action.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_begin_blocking_action.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_int_max.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_max.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_int_min.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_min.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_int_prod.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_prod.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_int_sum.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_sum.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_loop_balance_simple.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_loop_balance.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_loop_queue_addworker.3: -------------------------------------------------------------------------------- 1 | .TH qt_loop_queue_addworker 3 "JUNE 2010" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_loop_queue_addworker 4 | \- adds a worker to an ongoing loop 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_loop_queue_addworker 11 | .RI "(qqloop_handle_t *" loop , 12 | .br 13 | .ti +25 14 | .RI "qthread_shepherd_id_t " shep ); 15 | .SH DESCRIPTION 16 | This function adds a shepherd to the list of participating shepherds for a given loop queue. The function returns quickly, as all bookkeeping is then assumed by the original thread that called 17 | .BR qt_loop_queue_run (). 18 | .SH SEE ALSO 19 | .BR qt_loop (3), 20 | .BR qt_loop_balance (3), 21 | .BR qt_loop_queue_create (3), 22 | .BR qt_loop_queue_run (3), 23 | .BR qt_loopaccum_balance (3), 24 | .BR qt_loop_queue_create (3), 25 | .BR qt_loop_queue_addworker (3) 26 | -------------------------------------------------------------------------------- /man/man3/qt_loop_queue_run_there.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_loop_queue_run.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_loop_queue_setchunk.3: -------------------------------------------------------------------------------- 1 | .TH qt_loop_queue_setchunk 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_loop_queue_setchunk 4 | \- a funciton to specify a loop chunk size 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_loop_queue_setchunk 11 | .RI "(qqloop_handle_t *" loop , 12 | .RI size_t chunk ); 13 | 14 | .SH DESCRIPTION 15 | This function provides a way to specify the chunk size for a self-scheduled loop using the CHUNK scheduling pattern. This may only be safely used 16 | .I before 17 | .BR qt_loop_queue_run () 18 | or 19 | .BR qt_loop_queue_run_there () 20 | have been executed. 21 | .SH SEE ALSO 22 | .BR qt_loop (3), 23 | .BR qt_loop_balance (3), 24 | .BR qt_loopaccum_balance (3), 25 | .BR qt_loop_queue_create (3), 26 | .BR qt_loop_queue_addworker (3) 27 | -------------------------------------------------------------------------------- /man/man3/qt_loop_step.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_loop.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_read.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_pread.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_sinc_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qt_sinc_destroy 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_sinc_destroy 4 | \- deallocate and clean-up a sinc 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_sinc_destroy 11 | .RI "(qt_sinc_t *" sinc); 12 | 13 | .PP 14 | .I void 15 | .br 16 | .B qt_sinc_fini 17 | .RI "(qt_sinc_t *" sinc); 18 | 19 | .SH DESCRIPTION 20 | These functions deallocate and clean-up a qt_sinc_t object. The 21 | .BR qt_sinc_destroy () 22 | function is for use on sincs that were created with 23 | .BR qt_sinc_create (), 24 | whereas the 25 | .BR qt_sinc_fini () 26 | function is for use on sincs that were initialized with 27 | .BR qt_sinc_init (). 28 | The sinc is immediately destroyed and any internal memory associated with it is deallocated. 29 | .SH SEE ALSO 30 | .BR qt_sinc_create (3), 31 | .BR qt_sinc_expect (3), 32 | .BR qt_sinc_init (3), 33 | .BR qt_sinc_reset (3), 34 | .BR qt_sinc_submit (3), 35 | .BR qt_sinc_wait (3) 36 | -------------------------------------------------------------------------------- /man/man3/qt_sinc_expect.3: -------------------------------------------------------------------------------- 1 | .TH qt_sinc_expect 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_sinc_expect 4 | \- increase the number of expected submissions 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_sinc_expect 11 | .RI "(qt_sinc_t *" sinc, 12 | .br 13 | .ti +15 14 | .RI " size_t " count); 15 | .SH DESCRIPTION 16 | This function increases the number of expected submissions to the 17 | .I sinc 18 | qt_sinc_t object by 19 | .IR count . 20 | This operation can be performed at any time after the qt_sinc_t object has been initialized. 21 | .SH SEE ALSO 22 | .BR qt_sinc_create (3), 23 | .BR qt_sinc_destroy (3), 24 | .BR qt_sinc_fini (3), 25 | .BR qt_sinc_init (3), 26 | .BR qt_sinc_reset (3), 27 | .BR qt_sinc_submit (3), 28 | .BR qt_sinc_wait (3) 29 | -------------------------------------------------------------------------------- /man/man3/qt_sinc_fini.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_sinc_destroy.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_sinc_init.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_sinc_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_sinc_reset.3: -------------------------------------------------------------------------------- 1 | .TH qt_sinc_reset 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_sinc_reset 4 | \- restarts a sinc 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_sinc_reset 11 | .RI "(qt_sinc_t *" sinc, " size_t " expect); 12 | 13 | .SH DESCRIPTION 14 | This function restarts an existing qt_sinc_t object, regardless of what state it is in. Any partially accumulated values are discarded and replaced with the originally-specified initial value. Any remaining submissions that were expected are forgotten. The sinc is prepared to receive 15 | .I expect 16 | submissions. 17 | .SH SEE ALSO 18 | .BR qt_sinc_create (3), 19 | .BR qt_sinc_destroy (3), 20 | .BR qt_sinc_expect (3), 21 | .BR qt_sinc_fini (3), 22 | .BR qt_sinc_init (3), 23 | .BR qt_sinc_submit (3), 24 | .BR qt_sinc_wait (3) 25 | -------------------------------------------------------------------------------- /man/man3/qt_sinc_submit.3: -------------------------------------------------------------------------------- 1 | .TH qt_sinc_submit 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_sinc_submit 4 | \- submit to a sinc 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_sinc_submit 11 | .RI "(qt_sinc_t *restrict " sinc, 12 | .br 13 | .ti +15 14 | .RI " const void *restrict " value); 15 | 16 | .SH DESCRIPTION 17 | This function sends a submission to the specified 18 | .IR sinc . 19 | The submission may have a 20 | .I value 21 | associated with it, if the sinc was initialized to support a reduction operation. If so, the number of bytes read from the 22 | .I value 23 | address is the number configured when the sinc was initialized. 24 | .SH SEE ALSO 25 | .BR qt_sinc_create (3), 26 | .BR qt_sinc_destroy (3), 27 | .BR qt_sinc_expect (3), 28 | .BR qt_sinc_fini (3), 29 | .BR qt_sinc_init (3), 30 | .BR qt_sinc_reset (3), 31 | .BR qt_sinc_wait (3) 32 | -------------------------------------------------------------------------------- /man/man3/qt_sinc_wait.3: -------------------------------------------------------------------------------- 1 | .TH qt_sinc_wait 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_sinc_wait 4 | \- block caller until all expected submissions are submitted 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_sinc_wait 11 | .RI "(qt_sinc_t *restrict " sinc, 12 | .br 13 | .ti +15 14 | .RI " void *restrict " target); 15 | 16 | .SH DESCRIPTION 17 | This functions blocks the calling task until the specified 18 | .I sinc 19 | has received all of the submissions it expects. The number of expected submissions is permitted to increase while the calling thread is blocked, and will only increase the length of time the caller will block. Just before the calling task is released, if the sinc was initialized to perform a reduction operation, the result of that operation will be copied into the memory specified by 20 | .IR target . 21 | The number of bytes copied was specified when the sinc was initialized. 22 | .SH SEE ALSO 23 | .BR qt_sinc_create (3), 24 | .BR qt_sinc_destroy (3), 25 | .BR qt_sinc_expect (3), 26 | .BR qt_sinc_fini (3), 27 | .BR qt_sinc_init (3), 28 | .BR qt_sinc_reset (3), 29 | .BR qt_sinc_submit (3) 30 | -------------------------------------------------------------------------------- /man/man3/qt_team_critical_section.3: -------------------------------------------------------------------------------- 1 | .TH qt_team_critical_section 3 "NOVEMBER 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_team_critical_section 4 | \- marks a region of code that must not be interrupted by a eureka 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qt_team_critical_section 11 | .RI "(qt_team_critical_section_t " boundary ); 12 | .SH DESCRIPTION 13 | This function is used to mark a region of code that must not be interrupted by 14 | a eureka. This is primarily to allow small operations that do not work well 15 | when interrupted (such as printf()) to be performed in eureka-able code, and to 16 | allow for correct manipulation of shared data structures that require locking. 17 | If a eureka moment is reached by another thread while the current thread is 18 | within a critical section, the effect will be as if the current thread was able 19 | to complete its critical section just before the eureka moment was reached. 20 | .PP 21 | The argument, 22 | .IR boundary , 23 | may be one of two values: 24 | .I BEGIN 25 | and 26 | .IR END , 27 | indicating whether this is the beginning of a critical section or the end of one. Critical sections CAN be nested, if necessary. 28 | .SH SEE ALSO 29 | .BR qt_team_eureka (3) 30 | -------------------------------------------------------------------------------- /man/man3/qt_team_id.3: -------------------------------------------------------------------------------- 1 | .TH qt_team_id 3 "NOVEMBER 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_team_id 4 | \- returns the current team's unique ID number 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I unsigned int 9 | .br 10 | .B qt_team_id 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns the unique identifier associated with the qthread team to 14 | which the currently executing qthread belongs. Generally they are monotonically 15 | increasing values, but the value can wrap around after 16 | .BR UINT_MAX -1 17 | teams. 18 | .SH RETURN VALUE 19 | On success, the thread's team's identifying number is returned. If called from outside 20 | the Qthreads library, 21 | .B QTHREAD_NON_TEAM_ID 22 | is returned. The special value 23 | .B QTHREAD_NULL_TEAM_ID 24 | will never be returned. 25 | .SH SEE ALSO 26 | .BR qt_team_parent_id (3), 27 | .BR qthread_id (3), 28 | .BR qthread_shep (3) 29 | -------------------------------------------------------------------------------- /man/man3/qt_team_parent_id.3: -------------------------------------------------------------------------------- 1 | .TH qt_team_parent_id 3 "NOVEMBER 2012" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_team_parent_id 4 | \- returns the current team's parent's unique ID number 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I unsigned int 9 | .br 10 | .B qt_team_id 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns the unique identifier associated with the parent team of 14 | the team to which the currently executing qthread belongs. Generally they are 15 | monotonically increasing values, but the value can wrap around after 16 | .BR UINT_MAX -1 17 | teams. Only subteams have parent teams (or parent subteams). If this function 18 | is called from a team without a parent, it will return 19 | .B QTHREAD_NON_TEAM_ID. 20 | .SH RETURN VALUE 21 | On success, the thread's parent team's identifying number is returned. If called from outside 22 | the Qthreads library or from a parentless team, 23 | .B QTHREAD_NON_TEAM_ID 24 | is returned. The special value 25 | .B QTHREAD_NULL_TEAM_ID 26 | will never be returned. 27 | .SH SEE ALSO 28 | .BR qt_team_id (3), 29 | .BR qthread_id (3), 30 | .BR qthread_shep (3) 31 | -------------------------------------------------------------------------------- /man/man3/qt_uint_max.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_max.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_uint_min.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_min.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_uint_prod.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_prod.3 2 | -------------------------------------------------------------------------------- /man/man3/qt_uint_sum.3: -------------------------------------------------------------------------------- 1 | .so man3/qt_double_sum.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_cacheline.3: -------------------------------------------------------------------------------- 1 | .TH qt_cacheline 3 "OCTOBER 2009" libqthread "libqthread" 2 | .SH NAME 3 | .B qt_cacheline 4 | \- returns the cache line size 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qt_cacheline 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns the size of the local machine's top-level cache line in bytes. This is calculated only once. 14 | -------------------------------------------------------------------------------- /man/man3/qthread_cas.3: -------------------------------------------------------------------------------- 1 | .TH qthread_cas 3 "NOVEMBER 2009" libqthread "libqthread" 2 | .SH NAME 3 | .BR qthread_cas , 4 | .B qthread_cas_ptr 5 | \- atomically compare-and-swap a value 6 | .SH SYNOPSIS 7 | .B #include 8 | 9 | .I aligned_t 10 | .br 11 | .B qthread_cas 12 | .RI "(volatile aligned_t *" addr ", aligned_t " oldval , 13 | .ti +13 14 | .RI "aligned_t " newval ); 15 | .PP 16 | .I void * 17 | .br 18 | .B qthread_cas_ptr 19 | .RI "(void * volatile * " addr ", void * " oldval , 20 | .ti +17 21 | .RI "void * " newval ); 22 | .SH DESCRIPTION 23 | This function atomically compares the contents of the memory at 24 | .I addr 25 | with the value 26 | .I oldval 27 | and if they are the same, writes 28 | .I newval 29 | into that memory. If they are not the same, no change is made. In either case, 30 | the contents of 31 | .I addr 32 | are returned. In short, this is an atomic version of: 33 | .RS 34 | .PP 35 | .RI "retval = *" addr ; 36 | .br 37 | .RI "if (*" addr " == " oldval ") {" 38 | .RS 39 | .RI * addr " = " newval ; 40 | .RE 41 | } 42 | .br 43 | .RI "return retval;" 44 | .RE 45 | .PP 46 | This function uses architecture-specific assembly to achieve this, or compiler built-in functions, if they exist. 47 | .SH RETURN VALUE 48 | These functions will return the value of 49 | .RI * addr 50 | before any assignment is (potentially) performed. 51 | .SH SEE ALSO 52 | .BR qthread_incr (3) 53 | -------------------------------------------------------------------------------- /man/man3/qthread_cas_ptr.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_cas.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_dincr.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_incr.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_disable_worker.3: -------------------------------------------------------------------------------- 1 | .TH qthread_disable_worker 3 "AUGUST 2012" libqthread "libqthread" 2 | .SH NAME 3 | .BR qthread_disable_worker , 4 | .B qthread_enable_worker 5 | \- enable or disable a worker for thread scheduling 6 | .SH SYNOPSIS 7 | .B #include 8 | 9 | .I int 10 | .br 11 | .B qthread_disable_worker 12 | .RI "(qthread_worker_id_t " worker); 13 | .PP 14 | .I void 15 | .br 16 | .B qthread_enable_worker 17 | .RI "(qthread_worker_id_t " shep ); 18 | .SH DESCRIPTION 19 | These functions allow worker threads to be enabled and disabled. Workers usually start in the enabled state (the exception is when the QT_HWPAR environment variable is used). 20 | .PP 21 | Disabled workers cannot execute threads, but the presumption is that there are 22 | other workers on each shepherd. The disabled worker may continue executing its 23 | current thread until it either blocks, yields, or exits. Once that thread stops 24 | executing, the disabled worker monitors its status and waits to be either 25 | destroyed or re-enabled. 26 | .PP 27 | When a worker is re-enabled, it begins scheduling threads again. 28 | .SH RETURN VALUE 29 | On success, the specified worker thread is marked as disabled and the value 30 | .B QTHREAD_SUCCESS 31 | is returned. On failure, an error code is returned. 32 | .SH ERRORS 33 | .TP 12 34 | .B QTHREAD_NOT_ALLOWED 35 | The first worker, worker 0, cannot be disabled. 36 | -------------------------------------------------------------------------------- /man/man3/qthread_distance.3: -------------------------------------------------------------------------------- 1 | .TH qthread_distance 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_distance 4 | \- returns the distance between shepherds 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qthread_distance 11 | .RI "(const qthread_shepherd_id_t " src ", const qthread_shepherd_id_t " dest ); 12 | .SH DESCRIPTION 13 | This function returns the distance from the 14 | .I src 15 | shepherd to the memory of the 16 | .I dest 17 | shepherd. The distances are arbitrary, and may not exactly measure latency to 18 | memory, but do give an indication of relative distance. Shepherds that do not 19 | have a specific CPU affinity can be anywhere, and so the distance from or to 20 | such shepherds is considered 0. 21 | .RE 22 | .SH RETURN VALUE 23 | This function either returns the distance between the two specified shepherds, or returns 24 | .B QTHREAD_BADARGS 25 | if a shepherd identifier is invalid. 26 | .SH SEE ALSO 27 | .BR qthread_retloc (3), 28 | .BR qthread_stackleft (3), 29 | .BR qthread_id (3) 30 | -------------------------------------------------------------------------------- /man/man3/qthread_enable_shepherd.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_disable_shepherd.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_enable_worker.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_disable_worker.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_feb_barrier_destroy.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_feb_barrier_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_feb_barrier_enter.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_feb_barrier_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_feb_barrier_resize.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_feb_barrier_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_feb_status.3: -------------------------------------------------------------------------------- 1 | .TH qthread_feb_status 3 "NOVEMBER 2006" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_feb_status 4 | \- return the full/empty status of an address 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qthread_feb_status 11 | .RI "(const aligned_t *" addr ); 12 | .SH DESCRIPTION 13 | This function is just to assist with debugging. It returns 1 if the address is 14 | full, and 0 if the address is empty. It is thread-safe, and should be very 15 | quick. 16 | .SH SEE ALSO 17 | .BR qthread_empty (3), 18 | .BR qthread_fill (3), 19 | .BR qthread_writeF (3), 20 | .BR qthread_writeEF (3), 21 | .BR qthread_readFF (3), 22 | .BR qthread_readFE (3) 23 | -------------------------------------------------------------------------------- /man/man3/qthread_fill.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_empty.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_finalize.3: -------------------------------------------------------------------------------- 1 | .TH qthread_finalize 3 "NOVEMBER 2006" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_finalize 4 | \- terminate all qthreads and free library data stuctures 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qthread_finalize 11 | (void); 12 | .SH DESCRIPTION 13 | Use this function to clean up the qthreads environment after execution of the 14 | program has finished. This function will tell the shepherds to terminate at the 15 | next context switch, so only use it when you are certain that execution has 16 | completed. This function may be called multiple times safely. 17 | .SH SEE ALSO 18 | .BR qthread_initialize (3) 19 | -------------------------------------------------------------------------------- /man/man3/qthread_fincr.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_incr.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_fork_precond.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_fork.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_fork_precond_to.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_fork.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_fork_syncvar.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_fork.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_fork_syncvar_to.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_fork.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_fork_to.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_fork.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_get_tasklocal.3: -------------------------------------------------------------------------------- 1 | .TH qthread_get_tasklocal 3 "JUNE 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_get_tasklocal 4 | \- get pointer to the task-local data segment 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void * 9 | .br 10 | .B qthread_get_tasklocal 11 | .RI "(unsigned int " size ); 12 | .PP 13 | .SH DESCRIPTION 14 | Use this function to retrieve a pointer to the task-specific data segment. When successful, the return value is a pointer to a memory segment at least as large as 15 | .I size 16 | bytes; otherwise, 17 | .B NULL 18 | is returned. 19 | If 20 | .I size 21 | is larger than the current amount of allocated space, then the allocation will be increased to the requested size. 22 | The current size of the task-local data segment can be found using 23 | .BR qthread_size_tasklocal (). 24 | If the function is called from outside a qthread context, NULL is returned. 25 | .SH ENVIRONMENT 26 | The operation of 27 | .BR qthread_get_tasklocal () 28 | is modified by the following environment variable: 29 | .TP 4 30 | .B QTHREAD_TASKLOCAL_SIZE 31 | This variable sets the task-local data segment size at initialization. Changes to this value during the course of the program run are ignored; the value is only considered when 32 | .BR qthread_init () 33 | is run. 34 | .SH SEE ALSO 35 | .BR qthread_size_tasklocal (3) 36 | -------------------------------------------------------------------------------- /man/man3/qthread_id.3: -------------------------------------------------------------------------------- 1 | .TH qthread_id 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_id 4 | \- returns the qthread's unique ID number 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I unsigned int 9 | .br 10 | .B qthread_id 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns the unique identifier associated with the qthread 14 | .IR me . 15 | This is used mostly for debugging, as obtaining a global identifier requires 16 | synchronization. Unless otherwise configured, the qthread library assigns 17 | thread ids only when they are asked for. Generally they are monotonically 18 | increasing values, but the value can wrap around after 19 | .BR UINT_MAX -2 20 | threads. 21 | .SH RETURN VALUE 22 | On success, the thread's identifying number is returned. If called from outside 23 | the Qthreads library, 24 | .B QTHREAD_NON_TASK_ID 25 | is returned. The special value 26 | .B QTHREAD_NULL_TASK_ID 27 | will never be returned. 28 | .SH SEE ALSO 29 | .BR qthread_retloc (3), 30 | .BR qthread_shep (3), 31 | .BR qthread_stackleft (3) 32 | -------------------------------------------------------------------------------- /man/man3/qthread_initialize.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_init.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_lock.3: -------------------------------------------------------------------------------- 1 | .TH qthread_lock/unlock 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qthread_lock , 4 | .B qthread_unlock 5 | \- lock or unlock an address 6 | .SH SYNOPSIS 7 | .B #include 8 | 9 | .I int 10 | .br 11 | .B qthread_lock 12 | .RI "(aligned_t *" addr ); 13 | .PP 14 | .I int 15 | .br 16 | .B qthread_unlock 17 | .RI "(aligned_t *" addr ); 18 | .SH DESCRIPTION 19 | These functions are designed to implement FEB-like locking and unlocking that 20 | behaves much more like a mutex. 21 | .PP 22 | These are atomic and functional, but do not have the same semantics as full FEB 23 | locking/unlocking (namely, unlocking cannot block), however because of this, 24 | they have lower overhead. 25 | .SH RETURN VALUE 26 | On success, the memory address 27 | .I addr 28 | is marked locked or unlocked appropriately and 0 is returned. If unlocking an 29 | address that is already unlocked, 30 | .B QTHREAD_SUCCESS 31 | will be returned. On error, a non-zero error code is returned. 32 | .SH ERRORS 33 | .TP 12 34 | .B ENOMEM 35 | Not enough memory could be allocated for bookkeeping structures. 36 | .SH SEE ALSO 37 | .BR qthread_empty (3), 38 | .BR qthread_fill (3), 39 | .BR qthread_writeEF (3), 40 | .BR qthread_writeF (3), 41 | .BR qthread_readFF (3), 42 | .BR qthread_readFE (3) 43 | -------------------------------------------------------------------------------- /man/man3/qthread_migrate_to.3: -------------------------------------------------------------------------------- 1 | .TH qthread_migrate_to 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_migrate_to 4 | \- relocate a qthread to the target shepherd 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qthread_migrate_to 11 | .RI "(qthread_shepherd_id_t " shepherd ); 12 | .SH DESCRIPTION 13 | This is the function for moving a qthread to a different shepherd. 14 | .PP 15 | The first argument, 16 | .IR shepherd , 17 | is the identifier of the shepherd to move to. 18 | .PP 19 | When the call returns, the qthread will be running on the specified shepherd. 20 | .SH RETURN VALUE 21 | On success, 0 is returned. On error, a non-zero error code is returned. 22 | .SH ERRORS 23 | .TP 12 24 | .B QTHREAD_BADARGS 25 | Either the 26 | .I me 27 | value was invalid or the 28 | .I shepherd 29 | was too large. 30 | .SH SEE ALSO 31 | .BR qthread_fork_to (3) 32 | -------------------------------------------------------------------------------- /man/man3/qthread_num_shepherds.3: -------------------------------------------------------------------------------- 1 | .TH qthread_num_shepherds 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_num_shepherds 4 | \- returns the number of shepherds 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qthread_shepherd_id_t 9 | .br 10 | .B qthread_num_shepherds 11 | (); 12 | .SH DESCRIPTION 13 | This function returns the number of shepherds. This value is one larger than the largest valid shepherd id. 14 | .SH SEE ALSO 15 | .BR qthread_retloc (3), 16 | .BR qthread_stackleft (3), 17 | .BR qthread_id (3) 18 | -------------------------------------------------------------------------------- /man/man3/qthread_num_workers.3: -------------------------------------------------------------------------------- 1 | .TH qthread_num_workers 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_num_workers 4 | \- returns the number of workers 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qthread_worker_id_t 9 | .br 10 | .B qthread_num_workers 11 | (); 12 | .SH DESCRIPTION 13 | This function returns the number of workers. This value is one larger than the largest valid worker id. 14 | .SH SEE ALSO 15 | .BR qthread_worker (3) 16 | -------------------------------------------------------------------------------- /man/man3/qthread_queue_destroy.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_queue_create.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_queue_join.3: -------------------------------------------------------------------------------- 1 | .TH qthread_queue_join 3 "AUGUST 2013" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_queue_join 4 | \- enter a queue and block until the queue is released 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qthread_queue_join 11 | .RI "(qthread_queue_t " q ");" 12 | 13 | .SH DESCRIPTION 14 | This function causes the calling task to relinqush the processor and be queued up in the specified queue for later release. Effectively, it is similar to a 15 | .IR qthread_yield () 16 | call, but where another task must release the queue before this task executes again. 17 | 18 | .SH RETURN VALUES 19 | .BR qthread_queue_join () 20 | returns QTHREAD_SUCCESS if successful, or QTHREAD_BADARGS if 21 | .I q 22 | is invalid. 23 | 24 | .SH SEE ALSO 25 | .BR qthread_queue_create (3), 26 | .BR qthread_queue_destroy (3), 27 | .BR qthread_queue_length (3), 28 | .BR qthread_queue_release_all (3), 29 | .BR qthread_queue_release_one (3) 30 | -------------------------------------------------------------------------------- /man/man3/qthread_queue_length.3: -------------------------------------------------------------------------------- 1 | .TH qthread_queue_length 3 "AUGUST 2013" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_queue_length 4 | \- return the length of the queue 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I aligned_t 9 | .br 10 | .B qthread_queue_length 11 | .RI "(qthread_queue_t " q ");" 12 | 13 | .SH DESCRIPTION 14 | This function returns the number of tasks waiting in the queue. If the queue is not configured to keep track of the number of waiting tasks, it will return 0. 15 | 16 | .SH SEE ALSO 17 | .BR qthread_queue_create (3), 18 | .BR qthread_queue_destroy (3), 19 | .BR qthread_queue_join (3), 20 | .BR qthread_queue_release_all (3), 21 | .BR qthread_queue_release_one (3) 22 | -------------------------------------------------------------------------------- /man/man3/qthread_queue_release_all.3: -------------------------------------------------------------------------------- 1 | .TH qthread_queue_release 3 "AUGUST 2013" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_queue_release 4 | \- activate the tasks in the queue for scheduling and execution 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qthread_queue_release_one 11 | .RI "(qthread_queue_t " q ");" 12 | .PP 13 | .I int 14 | .br 15 | .B qthread_queue_release_all 16 | .RI "(qthread_queue_t " q ");" 17 | 18 | .SH DESCRIPTION 19 | These two functions are for emptying the specified queue 20 | .RB ( q ) 21 | and handing the tasks in the queue to the scheduler for execution. The 22 | .BR qthread_queue_release_one () 23 | function removes only a single task, in a fifo manner, and schedules it, while 24 | the 25 | .BR qthread_queue_release_all () 26 | function removes all of the tasks and schedules them. 27 | 28 | .SH RETURN VALUES 29 | Both functions return QTHREAD_SUCCESS on success, and an error otherwise. 30 | .SH SEE ALSO 31 | .BR qthread_queue_create (3), 32 | .BR qthread_queue_destroy (3), 33 | .BR qthread_queue_join (3), 34 | .BR qthread_queue_length (3) 35 | -------------------------------------------------------------------------------- /man/man3/qthread_queue_release_one.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_queue_release_all.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_retloc.3: -------------------------------------------------------------------------------- 1 | .TH qthread_retloc 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_retloc 4 | \- returns pointer to qthread's return location 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I aligned_t * 9 | .br 10 | .B qthread_retloc 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns the location that the return value of the current thread 14 | will be stored into, if one has been defined. 15 | .SH "RETURN VALUE" 16 | Returns a pointer to the location that the return value of the thread will be 17 | stored in. If the thread's return value will not be stored via FEBs, this 18 | function will return NULL. 19 | .SH SEE ALSO 20 | .BR qthread_id (3), 21 | .BR qthread_shep (3), 22 | .BR qthread_stackleft (3) 23 | -------------------------------------------------------------------------------- /man/man3/qthread_shep.3: -------------------------------------------------------------------------------- 1 | .TH qthread_shep 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_shep 4 | \- returns the qthread's shepherd ID 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qthread_shepherd_id_t 9 | .br 10 | .B qthread_shep 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns the shepherd identifier of the current thread. 14 | .SH RETURN VALUE 15 | This function either returns the ID number of the shepherd of the calling 16 | function, or returns 17 | .BR NO_SHEPHERD . 18 | .SH SEE ALSO 19 | .BR pthread_getspecific (3), 20 | .BR qthread_retloc (3), 21 | .BR qthread_stackleft (3), 22 | .BR qthread_worker (3), 23 | .BR qthread_id (3) 24 | -------------------------------------------------------------------------------- /man/man3/qthread_shep_ok.3: -------------------------------------------------------------------------------- 1 | .TH qthread_shep_ok 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_shep_ok 4 | \- check on whether a thread's shepherd is disabled 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qthread_shep_ok 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns zero if the current thread's shepherd has been disabled, 14 | and non-zero if the current thread's shepherd is enabled. 15 | .SH SEE ALSO 16 | .BR qthread_disable_shepherd (3), 17 | .BR qthread_enable_shepherd (3) 18 | -------------------------------------------------------------------------------- /man/man3/qthread_size_tasklocal.3: -------------------------------------------------------------------------------- 1 | .TH qthread_size_tasklocal 3 "JUNE 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_size_tasklocal 4 | \- returns the number of bytes allocated for task-local data 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I unsigned 9 | .br 10 | .B qthread_size_tasklocal 11 | (); 12 | .PP 13 | .SH DESCRIPTION 14 | This function to returns the number of bytes allocated for task-local data. 15 | .SH SEE ALSO 16 | .BR qthread_get_tasklocal (3) 17 | -------------------------------------------------------------------------------- /man/man3/qthread_sorted_sheps.3: -------------------------------------------------------------------------------- 1 | .TH qthread_sorted_sheps 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qthread_sorted_sheps , 4 | .B qthread_sorted_sheps_remote 5 | \- returns a list of other shepherds, sorted by their distance 6 | .SH SYNOPSIS 7 | .B #include 8 | 9 | .I const qthread_shepherd_id_t * 10 | .br 11 | .B qthread_sorted_sheps 12 | (void); 13 | .PP 14 | .I const qthread_shepherd_id_t * 15 | .br 16 | .B qthread_sorted_sheps_remote 17 | .RI "(const qthread_shepherd_id_t " src ); 18 | .SH DESCRIPTION 19 | This function returns a list of shepherds, sorted by their distance from either 20 | the current shepherd or the specified shepherd 21 | .IR src . 22 | This list is an array of qthread_shepherd_id_t objects with a length of one 23 | less than the number of shepherds (as determined by 24 | .BR qthread_num_shepherds ()). 25 | The source shepherd is not included in the list. 26 | .PP 27 | The returned array 28 | .I must not 29 | be altered. 30 | .SH RETURN VALUE 31 | These functions will return either a pointer to an array of 32 | qthread_shepherd_id_t objects, or NULL if the specified shepherd is either 33 | invalid or does not have a specific CPU affinity. 34 | -------------------------------------------------------------------------------- /man/man3/qthread_sorted_sheps_remote.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_sorted_sheps.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_stackleft.3: -------------------------------------------------------------------------------- 1 | .TH qthread_stackleft 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_stackleft 4 | \- returns the amount of space left in the thread's allocated stack 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I size_t 9 | .br 10 | .B qthread_stackleft 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns the number of bytes left in the stack. 14 | .SH RETURN VALUE 15 | If run on a qthread, it returns the number of bytes left in the stack, accurate 16 | to a small margin (on the order of 10 bytes). Otherwise it returns 0. 17 | .SH SEE ALSO 18 | .BR qthread_id (3), 19 | .BR qthread_retloc (3), 20 | .BR qthread_shep (3) 21 | -------------------------------------------------------------------------------- /man/man3/qthread_syncvar_empty.3: -------------------------------------------------------------------------------- 1 | .TH qthread_syncvar_empty/fill 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .BR qthread_syncvar_empty , 4 | .B qthread_syncvar_fill 5 | \- sets the given syncvar to either "empty" or "full" 6 | .SH SYNOPSIS 7 | .B #include 8 | 9 | .I int 10 | .br 11 | .B qthread_syncvar_empty 12 | .RI "(syncvar_t *" dest ); 13 | .PP 14 | .I int 15 | .br 16 | .B qthread_syncvar_fill 17 | .RI "(syncvar_t *" dest ); 18 | .SH DESCRIPTION 19 | The 20 | .BR qthread_syncvar_empty () 21 | and 22 | .BR qthread_syncvar_fill () 23 | functions assert the empty or full state of the given 24 | .I dest 25 | addresses. They do not wait for the addresses to be in any particular state. 26 | .SH RETURN VALUE 27 | On success, the full/empty bits are modified and 0 is returned. On error, an 28 | non-zero error code is returned. 29 | .SH ERRORS 30 | .TP 12 31 | .B QTHREAD_TIMEOUT 32 | Could not obtain the lock on the syncvar_t's status bits. This may be caused by 33 | many things, including memory corruption, invalid syncvar, or even absurdly 34 | excessive contention (because its protected by a naive spinlock rather than a 35 | fair spinlock). 36 | .SH SEE ALSO 37 | .BR qthread_syncvar_writeF (3), 38 | .BR qthread_syncvar_writeEF (3), 39 | .BR qthread_syncvar_readFF (3), 40 | .BR qthread_syncvar_readFE (3) 41 | -------------------------------------------------------------------------------- /man/man3/qthread_syncvar_fill.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_syncvar_empty.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_syncvar_status.3: -------------------------------------------------------------------------------- 1 | .TH qthread_syncvar_status 3 "JUNE 2010" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_syncvar_status 4 | \- return the full/empty status of a syncvar_t 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I int 9 | .br 10 | .B qthread_syncvar_status 11 | .RI "(syncvar_t *" addr ); 12 | .SH DESCRIPTION 13 | This function returns 1 if the address is full, and 0 if the address is empty. 14 | It is thread-safe, and should be very quick. On 64-bit platforms, it usually 15 | reduces to a read and a bitshift. 16 | .SH SEE ALSO 17 | .BR qthread_syncvar_empty (3), 18 | .BR qthread_syncvar_fill (3), 19 | .BR qthread_syncvar_writeFE (3), 20 | .BR qthread_syncvar_writeF (3), 21 | .BR qthread_syncvar_readFE (3), 22 | .BR qthread_syncvar_readFF (3) 23 | -------------------------------------------------------------------------------- /man/man3/qthread_syncvar_writeEF_const.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_syncvar_writeEF.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_syncvar_writeF_const.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_syncvar_writeF.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_unlock.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_lock.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_worker.3: -------------------------------------------------------------------------------- 1 | .TH qthread_worker 3 "JUNE 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_worker 4 | \- returns the qthread's current worker ID 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qthread_worker_id_t 9 | .br 10 | .B qthread_worker 11 | .RI "(qthread_shepherd_id_t *" shep ); 12 | .SH DESCRIPTION 13 | This function returns the ID of the worker that the current thread is executing on. If 14 | .I shep 15 | is non-NULL, the value of the current shepherd identifier is written to that location. 16 | .P 17 | Note that the current worker ID is transient, and is likely to change, for 18 | example, after a call to 19 | .BR qthread_yield (). 20 | This value is dependent on how many workers are currently active. 21 | .SH RETURN VALUE 22 | This function either returns the ID number of the current worker of the calling 23 | function, or returns 24 | .BR NO_WORKER . 25 | .SH SEE ALSO 26 | .BR pthread_getspecific (3), 27 | .BR qthread_retloc (3), 28 | .BR pthread_shep (3), 29 | .BR qthread_stackleft (3), 30 | .BR qthread_id (3) 31 | -------------------------------------------------------------------------------- /man/man3/qthread_worker_unique.3: -------------------------------------------------------------------------------- 1 | .TH qthread_worker_unique 3 "JUNE 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_worker_unique 4 | \- returns the qthread's current worker's stable ID 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qthread_worker_id_t 9 | .br 10 | .B qthread_worker_unique 11 | .RI "(qthread_shepherd_id_t *" shep ); 12 | .SH DESCRIPTION 13 | This function returns the stable ID of the worker that the current thread is executing on. If 14 | .I shep 15 | is non-NULL, the value of the current shepherd identifier is written to that location. 16 | .P 17 | Note that the current worker ID is transient, and is likely to change, for 18 | example, after a call to 19 | .BR qthread_yield (). 20 | This value is not dependent on how many workers have been disabled. 21 | .SH RETURN VALUE 22 | This function either returns the ID number of the current worker of the calling 23 | function, or returns 24 | .BR NO_WORKER . 25 | .SH SEE ALSO 26 | .BR pthread_getspecific (3), 27 | .BR qthread_retloc (3), 28 | .BR pthread_shep (3), 29 | .BR qthread_stackleft (3), 30 | .BR qthread_id (3) 31 | -------------------------------------------------------------------------------- /man/man3/qthread_writeEF_const.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_writeEF.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_writeF_const.3: -------------------------------------------------------------------------------- 1 | .so man3/qthread_writeF.3 2 | -------------------------------------------------------------------------------- /man/man3/qthread_yield.3: -------------------------------------------------------------------------------- 1 | .TH qthread_yield 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qthread_yield 4 | \- release the CPU, allow other qthreads to run 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qthread_yield 11 | (void); 12 | .SH DESCRIPTION 13 | This function allows a qthread to explicitly interrupt computation and give 14 | other qthreads the chance to execute even though it has not blocked. This can 15 | be useful for things like busy-waits or cooperative multitasking. Without using 16 | this function, there is no guarantee that other qthreads will have a chance to 17 | execute until the currently running qthread performs a synchronization 18 | operation. 19 | If this function is called from a non-qthread or before the 20 | .BR qthread_initialize () 21 | has been run, it does nothing. 22 | -------------------------------------------------------------------------------- /man/man3/qtimer_create.3: -------------------------------------------------------------------------------- 1 | .TH qtimer_create 3 "JUNE 2010" libqthread "libqthread" 2 | .SH NAME 3 | .B qtimer_create 4 | \- allocate a qtimer 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I qtimer_t 9 | .br 10 | .B qtimer_create 11 | (void); 12 | .SH DESCRIPTION 13 | This function initializes a qtimer_t object and prepares for taking high-resolution low-overhead timings (on supported platforms). 14 | .SH RETURN VALUES 15 | Returns an initialized qtimer_t object. 16 | .SH SEE ALSO 17 | .BR qtimer_destroy (3), 18 | .BR qtimer_start (3), 19 | .BR qtimer_stop (3), 20 | .BR qtimer_secs (3) 21 | -------------------------------------------------------------------------------- /man/man3/qtimer_destroy.3: -------------------------------------------------------------------------------- 1 | .TH qtimer_destroy 3 "JUNE 2010" libqthread "libqthread" 2 | .SH NAME 3 | .B qtimer_destroy 4 | \- deallocate a qtimer 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qtimer_destroy 11 | .RI "(qtimer_t " timer ); 12 | .SH DESCRIPTION 13 | This function deallocates the 14 | .I timer 15 | object; it must have been allocated with the 16 | .BR qtimer_create () 17 | function. 18 | .SH SEE ALSO 19 | .BR qtimer_create (3), 20 | .BR qtimer_start (3), 21 | .BR qtimer_stop (3), 22 | .BR qtimer_secs (3) 23 | -------------------------------------------------------------------------------- /man/man3/qtimer_fastrand.3: -------------------------------------------------------------------------------- 1 | .TH qtimer_fastrand 3 "APRIL 2011" libqthread "libqthread" 2 | .SH NAME 3 | .B qtimer_fastrand 4 | \- generate a quick random number based on the high-resolution timer 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I long 9 | .br 10 | .B qtimer_fastrand 11 | (void); 12 | .SH DESCRIPTION 13 | This function returns a quick random number based on the high-resolution timer. 14 | The return value is between -2^31 and 2^31. 15 | .SH SEE ALSO 16 | .BR qtimer_create (3), 17 | .BR qtimer_destroy (3), 18 | .BR qtimer_start (3), 19 | .BR qtimer_stop (3) 20 | -------------------------------------------------------------------------------- /man/man3/qtimer_secs.3: -------------------------------------------------------------------------------- 1 | .TH qtimer_secs 3 "JUNE 2010" libqthread "libqthread" 2 | .SH NAME 3 | .B qtimer_secs 4 | \- calculate the elapsed time in seconds 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I double 9 | .br 10 | .B qtimer_secs 11 | .RI "(qtimer_t " timer ); 12 | .SH DESCRIPTION 13 | This function calculates the elapsed time of the timer and returns that length as a double-precision value in the unit of seconds. The return value is undefined if the timer has not yet been both started and stopped, in that order. 14 | .SH SEE ALSO 15 | .BR qtimer_create (3), 16 | .BR qtimer_destroy (3), 17 | .BR qtimer_start (3), 18 | .BR qtimer_stop (3) 19 | -------------------------------------------------------------------------------- /man/man3/qtimer_start.3: -------------------------------------------------------------------------------- 1 | .TH qtimer_start 3 "JUNE 2010" libqthread "libqthread" 2 | .SH NAME 3 | .BR qtimer_start ", " qtimer_stop 4 | \- start/stop a qtimer timing 5 | .SH SYNOPSIS 6 | .B #include 7 | 8 | .I void 9 | .br 10 | .B qtimer_start 11 | .RI "(qtimer_t " timer ); 12 | 13 | .I void 14 | .br 15 | .B qtimer_stop 16 | .RI "(qtimer_t " timer ); 17 | .SH DESCRIPTION 18 | These functions start and stop (respectively) the timing of the qtimer 19 | .IR timer . 20 | .PP 21 | Before using these functions, the 22 | .I timer 23 | must have been initialized with 24 | .BR qtimer_create () 25 | and must not have been destroyed with 26 | .BR qtimer_destroy (). 27 | .PP 28 | In general, timers should not be started multiple times in a row without an 29 | intervening stop, nor should they be stopped multiple times in a row without an 30 | intervening start, though in most cases this will not cause an error, but will 31 | just behave as a "last operation wins". Timers should also be started before 32 | they are stopped, though in most cases this will not cause an error, but will 33 | instead cause the value of 34 | .BR qtimer_secs () 35 | to be undefined. However, the safety of mis-using qtimers is not guaranteed. 36 | .SH SEE ALSO 37 | .BR qtimer_create (3), 38 | .BR qtimer_destroy (3), 39 | .BR qtimer_secs (3) 40 | -------------------------------------------------------------------------------- /man/man3/qtimer_stop.3: -------------------------------------------------------------------------------- 1 | .so man3/qtimer_start.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_int_max.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_max.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_int_min.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_min.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_int_mult.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_mult.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_int_sum.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_sum.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_mergesort.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_qsort.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_uint_max.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_max.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_uint_min.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_min.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_uint_mult.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_mult.3 2 | -------------------------------------------------------------------------------- /man/man3/qutil_uint_sum.3: -------------------------------------------------------------------------------- 1 | .so man3/qutil_double_sum.3 2 | -------------------------------------------------------------------------------- /qthread-config.cmake.in: -------------------------------------------------------------------------------- 1 | include("${CMAKE_CURRENT_LIST_DIR}/qthread.cmake") 2 | -------------------------------------------------------------------------------- /qthread.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: qthreads 7 | Description: Lightweight locality-aware user-level threading runtime. 8 | URL: https://github.com/sandialabs/qthreads 9 | Version: @VERSION@ 10 | Cflags: -I${includedir} 11 | Libs: -L${libdir} -lqthread 12 | Libs.private: @LIBS@ 13 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | libqthread.la 2 | -------------------------------------------------------------------------------- /src/affinity/README.binders: -------------------------------------------------------------------------------- 1 | Binders is a low level affinity layer for precise control over where workers and 2 | shepherds are allocated. It is implemented as a colon-seperated list of 3 | cpustrings, where each cpustring is a shepherd. It is controlled by the 4 | environment variable QT_CPUBIND. 5 | 6 | Example usages: 7 | 8 | Two shepherds, first has workers on cpus 0-3, second has workers on cpus 4-7. 9 | QT_CPUBIND=0-3:4-7 10 | 11 | One shepherd, workers on cpus 0,4,8,12 12 | QT_CPUBIND=0,4,8,12 13 | -------------------------------------------------------------------------------- /src/affinity/no.c: -------------------------------------------------------------------------------- 1 | #include "qt_affinity.h" 2 | #include "qt_alloc.h" 3 | #include "qt_asserts.h" 4 | #include "qt_envariables.h" 5 | #include "shufflesheps.h" 6 | 7 | void INTERNAL qt_affinity_init(qthread_shepherd_id_t *nbshepherds, 8 | qthread_worker_id_t *nbworkers, 9 | size_t *hw_par) { 10 | if (*nbshepherds == 0) { *nbshepherds = 1; } 11 | if (*nbworkers == 0) { *nbworkers = 1; } 12 | } 13 | 14 | void INTERNAL qt_affinity_deinit(void) {} 15 | 16 | void INTERNAL qt_affinity_set(qthread_worker_t *me, unsigned int Q_UNUSED(nw)) { 17 | } 18 | 19 | int INTERNAL qt_affinity_gendists(qthread_shepherd_t *sheps, 20 | qthread_shepherd_id_t nshepherds) { 21 | for (size_t i = 0; i < nshepherds; ++i) { 22 | sheps[i].sorted_sheplist = 23 | qt_calloc(nshepherds - 1, sizeof(qthread_shepherd_id_t)); 24 | sheps[i].shep_dists = qt_calloc(nshepherds, sizeof(unsigned int)); 25 | for (size_t j = 0, k = 0; j < nshepherds; ++j) { 26 | if (j != i) { 27 | assert(k < (nshepherds - 1)); 28 | sheps[i].shep_dists[j] = 10; 29 | sheps[i].sorted_sheplist[k++] = j; 30 | } 31 | } 32 | // no need to sort; they're all equidistant 33 | shuffle_sheps(sheps[i].sorted_sheplist, nshepherds - 1); 34 | } 35 | return QTHREAD_SUCCESS; 36 | } 37 | 38 | /* vim:set expandtab: */ 39 | -------------------------------------------------------------------------------- /src/affinity/shepcomp.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static qthread_shepherd_id_t shepcomp_src; 4 | 5 | static int qthread_internal_shepcomp(void const *a, void const *b) { 6 | int a_dist = qthread_distance(shepcomp_src, *(qthread_shepherd_id_t *)a); 7 | int b_dist = qthread_distance(shepcomp_src, *(qthread_shepherd_id_t *)b); 8 | 9 | return a_dist - b_dist; 10 | } 11 | -------------------------------------------------------------------------------- /src/alloc/base.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* System Headers */ 5 | #include /* for getpagesize() */ 6 | 7 | /* Internal Headers */ 8 | #include "qt_alloc.h" 9 | #include "qt_asserts.h" 10 | 11 | /* local constants */ 12 | size_t _pagesize = 0; 13 | 14 | void *qt_malloc(size_t size) { return malloc(size); } 15 | 16 | void qt_free(void *ptr) { free(ptr); } 17 | 18 | void *qt_calloc(size_t nmemb, size_t size) { return calloc(nmemb, size); } 19 | 20 | void *qt_realloc(void *ptr, size_t size) { return realloc(ptr, size); } 21 | 22 | void qt_internal_alignment_init(void) { _pagesize = getpagesize(); } 23 | 24 | void *qt_internal_aligned_alloc(size_t alloc_size, 25 | uint_fast16_t alignment_small) { 26 | size_t alignment = alignment_small; 27 | // round alloc_size up to the nearest multiple of alignment 28 | // since that's required by the standard aligned_alloc 29 | // and the implementation on OSX actually enforces that. 30 | if (alignment) { 31 | alloc_size = ((alloc_size + (alignment - 1ull)) / alignment) * alignment; 32 | } 33 | return aligned_alloc(alignment, alloc_size); 34 | } 35 | 36 | void qt_internal_aligned_free(void *ptr, uint_fast16_t alignment) { 37 | qt_free(ptr); 38 | } 39 | 40 | /* vim:set expandtab: */ 41 | -------------------------------------------------------------------------------- /src/alloc/chapel.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "chpl-linefile-support.h" 7 | #include "chpl-mem.h" 8 | 9 | void *qt_malloc(size_t size) { 10 | return chpl_mem_alloc( 11 | size, CHPL_RT_MD_TASK_LAYER_UNSPEC, 0, CHPL_FILE_IDX_INTERNAL); 12 | } 13 | 14 | void qt_free(void *ptr) { chpl_mem_free(ptr, 0, CHPL_FILE_IDX_INTERNAL); } 15 | 16 | void *qt_calloc(size_t nmemb, size_t size) { 17 | return chpl_mem_calloc( 18 | nmemb, size, CHPL_RT_MD_TASK_LAYER_UNSPEC, 0, CHPL_FILE_IDX_INTERNAL); 19 | } 20 | 21 | void *qt_realloc(void *ptr, size_t size) { 22 | return chpl_mem_realloc( 23 | ptr, size, CHPL_RT_MD_TASK_LAYER_UNSPEC, 0, CHPL_FILE_IDX_INTERNAL); 24 | } 25 | 26 | /* local constants */ 27 | size_t _pagesize = 0; 28 | 29 | void qt_internal_alignment_init(void) { _pagesize = getpagesize(); } 30 | 31 | void *qt_internal_aligned_alloc(size_t alloc_size, uint_fast16_t alignment) { 32 | return chpl_mem_memalign(alignment, 33 | alloc_size, 34 | CHPL_RT_MD_TASK_LAYER_UNSPEC, 35 | 0, 36 | CHPL_FILE_IDX_INTERNAL); 37 | } 38 | 39 | void qt_internal_aligned_free(void *ptr, uint_fast16_t alignment) { 40 | chpl_mem_free(ptr, 0, CHPL_FILE_IDX_INTERNAL); 41 | } 42 | -------------------------------------------------------------------------------- /src/ds/qpool.c: -------------------------------------------------------------------------------- 1 | /* Internal Headers */ 2 | #include "qthread/qpool.h" 3 | #include "qt_asserts.h" 4 | #include "qt_mpool.h" 5 | #include "qt_visibility.h" 6 | 7 | API_FUNC qpool *qpool_create_aligned(size_t const isize, size_t alignment) { 8 | return qt_mpool_create_aligned(isize, alignment); 9 | } 10 | 11 | API_FUNC qpool *qpool_create(size_t const item_size) { 12 | return qpool_create_aligned(item_size, 0); 13 | } 14 | 15 | API_FUNC void *qpool_alloc(qpool *pool) { return qt_mpool_alloc(pool); } 16 | 17 | API_FUNC void qpool_free(qpool *restrict pool, void *restrict mem) { 18 | qt_mpool_free(pool, mem); 19 | } 20 | 21 | API_FUNC void qpool_destroy(qpool *pool) { qt_mpool_destroy(pool); } 22 | 23 | /* vim:set expandtab: */ 24 | -------------------------------------------------------------------------------- /src/qtimer/gethrtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "qt_alloc.h" 8 | 9 | struct qtimer_s { 10 | hrtime_t start; 11 | hrtime_t stop; 12 | }; 13 | 14 | void API_FUNC qtimer_start(qtimer_t q) { q->start = gethrtime(); } 15 | 16 | unsigned long API_FUNC qtimer_fastrand(void) { 17 | return (unsigned long)(gethrtime()); 18 | } 19 | 20 | void API_FUNC qtimer_stop(qtimer_t q) { q->stop = gethrtime(); } 21 | 22 | double qtimer_wtime(void) { return ((double)gethrtime()) * 1e-9; } 23 | 24 | double qtimer_res(void) { return 1.0 / sysconf(_SC_CLK_TCK); } 25 | 26 | double API_FUNC qtimer_secs(qtimer_t q) { 27 | return ((double)(q->stop - q->start)) * 1e-9; 28 | } 29 | 30 | qtimer_t API_FUNC qtimer_create() { 31 | return qt_calloc(1, sizeof(struct qtimer_s)); 32 | } 33 | 34 | void API_FUNC qtimer_destroy(qtimer_t q) { FREE(q, sizeof(struct qtimer_s)); } 35 | 36 | /* vim:set expandtab: */ 37 | -------------------------------------------------------------------------------- /src/qtimer/gettimeofday.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include "qt_alloc.h" 9 | 10 | struct qtimer_s { 11 | struct timeval start, stop; 12 | }; 13 | 14 | void API_FUNC qtimer_start(qtimer_t q) { gettimeofday(&(q->start), NULL); } 15 | 16 | unsigned long API_FUNC qtimer_fastrand(void) { 17 | struct timeval s; 18 | 19 | gettimeofday(&(s), NULL); 20 | return (unsigned long)(s.tv_usec); 21 | } 22 | 23 | double qtimer_wtime(void) { 24 | struct timeval s; 25 | 26 | gettimeofday(&(s), NULL); 27 | return s.tv_sec + (s.tv_usec * 1e-6); 28 | } 29 | 30 | double qtimer_res(void) { return 1.0 / sysconf(_SC_CLK_TCK); } 31 | 32 | void API_FUNC qtimer_stop(qtimer_t q) { gettimeofday(&(q->stop), NULL); } 33 | 34 | double API_FUNC qtimer_secs(qtimer_t q) { 35 | return (q->stop.tv_sec + q->stop.tv_usec * 1e-6) - 36 | (q->start.tv_sec + q->start.tv_usec * 1e-6); 37 | } 38 | 39 | qtimer_t API_FUNC qtimer_create() { 40 | return qt_calloc(1, sizeof(struct qtimer_s)); 41 | } 42 | 43 | void API_FUNC qtimer_destroy(qtimer_t q) { FREE(q, sizeof(struct qtimer_s)); } 44 | 45 | /* vim:set expandtab: */ 46 | -------------------------------------------------------------------------------- /src/syscalls/accept.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include /* for SYS_accept and others */ 5 | #include 6 | 7 | /* Public Headers */ 8 | #include "qthread/qt_syscalls.h" 9 | 10 | /* Internal Headers */ 11 | #include "qt_asserts.h" 12 | #include "qt_io.h" 13 | #include "qt_qthread_mgmt.h" 14 | #include "qthread_innards.h" /* for qlib */ 15 | 16 | int qt_accept(int socket, 17 | struct sockaddr *restrict address, 18 | socklen_t *restrict address_len) { 19 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 20 | int ret; 21 | qthread_t *me = qthread_internal_self(); 22 | 23 | assert(job); 24 | job->next = NULL; 25 | job->thread = me; 26 | job->op = ACCEPT; 27 | memcpy(&job->args[0], &socket, sizeof(int)); 28 | job->args[1] = (uintptr_t)address; 29 | job->args[2] = (uintptr_t)address_len; 30 | 31 | assert(me->rdata); 32 | me->rdata->blockedon.io = job; 33 | atomic_store_explicit( 34 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 35 | qthread_back_to_master(me); 36 | ret = job->ret; 37 | errno = job->err; 38 | FREE_SYSCALLJOB(job); 39 | return ret; 40 | } 41 | 42 | /* vim:set expandtab: */ 43 | -------------------------------------------------------------------------------- /src/syscalls/connect.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include /* for SYS_accept and others */ 5 | #include 6 | 7 | /* Public Headers */ 8 | #include "qthread/qt_syscalls.h" 9 | 10 | /* Internal Headers */ 11 | #include "qt_asserts.h" 12 | #include "qt_io.h" 13 | #include "qt_qthread_mgmt.h" 14 | #include "qthread_innards.h" /* for qlib */ 15 | 16 | int qt_connect(int socket, 17 | const struct sockaddr *address, 18 | socklen_t address_len) { 19 | qthread_t *me = qthread_internal_self(); 20 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 21 | int ret; 22 | 23 | assert(job); 24 | job->next = NULL; 25 | job->thread = me; 26 | job->op = CONNECT; 27 | memcpy(&job->args[0], &socket, sizeof(int)); 28 | job->args[1] = (uintptr_t)address; 29 | job->args[2] = (uintptr_t)address_len; 30 | 31 | assert(me->rdata); 32 | me->rdata->blockedon.io = job; 33 | atomic_store_explicit( 34 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 35 | qthread_back_to_master(me); 36 | ret = job->ret; 37 | errno = job->err; 38 | FREE_SYSCALLJOB(job); 39 | return ret; 40 | } 41 | 42 | /* vim:set expandtab: */ 43 | -------------------------------------------------------------------------------- /src/syscalls/poll.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include /* for SYS_accept and others */ 4 | #include 5 | 6 | /* Public Headers */ 7 | #include "qthread/qt_syscalls.h" 8 | 9 | /* Internal Headers */ 10 | #include "qt_asserts.h" 11 | #include "qt_io.h" 12 | #include "qt_qthread_mgmt.h" 13 | #include "qthread_innards.h" /* for qlib */ 14 | 15 | int qt_poll(struct pollfd fds[], nfds_t nfds, int timeout) { 16 | qthread_t *me = qthread_internal_self(); 17 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 18 | int ret; 19 | 20 | assert(job); 21 | job->next = NULL; 22 | job->thread = me; 23 | job->op = POLL; 24 | job->args[0] = (uintptr_t)&(fds[0]); 25 | memcpy(&job->args[1], &nfds, sizeof(nfds_t)); 26 | memcpy(&job->args[2], &timeout, sizeof(int)); 27 | 28 | assert(me->rdata); 29 | 30 | me->rdata->blockedon.io = job; 31 | atomic_store_explicit( 32 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 33 | qthread_back_to_master(me); 34 | ret = job->ret; 35 | errno = job->err; 36 | FREE_SYSCALLJOB(job); 37 | return ret; 38 | } 39 | 40 | /* vim:set expandtab: */ 41 | -------------------------------------------------------------------------------- /src/syscalls/pread.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include 5 | 6 | #include /* for SYS_accept and others */ 7 | #include 8 | 9 | /* Public Headers */ 10 | #include "qthread/qt_syscalls.h" 11 | 12 | /* Internal Headers */ 13 | #include "qt_asserts.h" 14 | #include "qt_io.h" 15 | #include "qt_qthread_mgmt.h" 16 | #include "qthread_innards.h" /* for qlib */ 17 | 18 | ssize_t qt_pread(int filedes, void *buf, size_t nbyte, off_t offset) { 19 | qthread_t *me = qthread_internal_self(); 20 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 21 | ssize_t ret; 22 | 23 | assert(job); 24 | job->next = NULL; 25 | job->thread = me; 26 | job->op = PREAD; 27 | memcpy(&job->args[0], &filedes, sizeof(int)); 28 | job->args[1] = (uintptr_t)buf; 29 | job->args[2] = (uintptr_t)nbyte; 30 | memcpy(&job->args[3], &offset, sizeof(off_t)); 31 | 32 | assert(me->rdata); 33 | 34 | me->rdata->blockedon.io = job; 35 | atomic_store_explicit( 36 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 37 | qthread_back_to_master(me); 38 | ret = job->ret; 39 | errno = job->err; 40 | FREE_SYSCALLJOB(job); 41 | return ret; 42 | } 43 | 44 | /* vim:set expandtab: */ 45 | -------------------------------------------------------------------------------- /src/syscalls/pwrite.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include 5 | 6 | #include /* for SYS_accept and others */ 7 | #include 8 | 9 | /* Public Headers */ 10 | #include "qthread/qt_syscalls.h" 11 | 12 | /* Internal Headers */ 13 | #include "qt_asserts.h" 14 | #include "qt_io.h" 15 | #include "qt_qthread_mgmt.h" 16 | #include "qthread_innards.h" /* for qlib */ 17 | 18 | ssize_t qt_pwrite(int filedes, void const *buf, size_t nbyte, off_t offset) { 19 | qthread_t *me = qthread_internal_self(); 20 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 21 | ssize_t ret; 22 | 23 | assert(job); 24 | job->next = NULL; 25 | job->thread = me; 26 | job->op = PWRITE; 27 | memcpy(&job->args[0], &filedes, sizeof(int)); 28 | job->args[1] = (uintptr_t)buf; 29 | memcpy(&job->args[2], &nbyte, sizeof(size_t)); 30 | memcpy(&job->args[3], &offset, sizeof(off_t)); 31 | 32 | assert(me->rdata); 33 | 34 | me->rdata->blockedon.io = job; 35 | atomic_store_explicit( 36 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 37 | qthread_back_to_master(me); 38 | ret = job->ret; 39 | errno = job->err; 40 | FREE_SYSCALLJOB(job); 41 | return ret; 42 | } 43 | 44 | /* vim:set expandtab: */ 45 | -------------------------------------------------------------------------------- /src/syscalls/read.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include 5 | 6 | #include /* for SYS_accept and others */ 7 | #include 8 | 9 | /* Public Headers */ 10 | #include "qthread/qt_syscalls.h" 11 | 12 | /* Internal Headers */ 13 | #include "qt_asserts.h" 14 | #include "qt_io.h" 15 | #include "qt_qthread_mgmt.h" 16 | #include "qthread_innards.h" /* for qlib */ 17 | 18 | ssize_t qt_read(int filedes, void *buf, size_t nbyte) { 19 | qthread_t *me = qthread_internal_self(); 20 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 21 | ssize_t ret; 22 | 23 | assert(job); 24 | job->next = NULL; 25 | job->thread = me; 26 | job->op = READ; 27 | memcpy(&job->args[0], &filedes, sizeof(int)); 28 | job->args[1] = (uintptr_t)buf; 29 | job->args[2] = (uintptr_t)nbyte; 30 | 31 | assert(me->rdata); 32 | 33 | me->rdata->blockedon.io = job; 34 | atomic_store_explicit( 35 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 36 | qthread_back_to_master(me); 37 | ret = job->ret; 38 | errno = job->err; 39 | FREE_SYSCALLJOB(job); 40 | return ret; 41 | } 42 | 43 | /* vim:set expandtab: */ 44 | -------------------------------------------------------------------------------- /src/syscalls/select.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include 5 | 6 | #include /* for SYS_accept and others */ 7 | #include 8 | 9 | /* Public Headers */ 10 | #include "qthread/qt_syscalls.h" 11 | 12 | /* Internal Headers */ 13 | #include "qt_asserts.h" 14 | #include "qt_io.h" 15 | #include "qt_qthread_mgmt.h" 16 | #include "qthread_innards.h" /* for qlib */ 17 | 18 | int qt_select(int nfds, 19 | fd_set *restrict readfds, 20 | fd_set *restrict writefds, 21 | fd_set *restrict errorfds, 22 | struct timeval *restrict timeout) { 23 | qthread_t *me = qthread_internal_self(); 24 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 25 | int ret; 26 | 27 | assert(job); 28 | job->next = NULL; 29 | job->thread = me; 30 | job->op = SELECT; 31 | memcpy(&job->args[0], &nfds, sizeof(int)); 32 | job->args[1] = (uintptr_t)readfds; 33 | job->args[2] = (uintptr_t)writefds; 34 | job->args[3] = (uintptr_t)errorfds; 35 | job->args[4] = (uintptr_t)timeout; 36 | 37 | assert(me->rdata); 38 | 39 | me->rdata->blockedon.io = job; 40 | atomic_store_explicit( 41 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 42 | qthread_back_to_master(me); 43 | ret = job->ret; 44 | errno = job->err; 45 | FREE_SYSCALLJOB(job); 46 | return ret; 47 | } 48 | 49 | /* vim:set expandtab: */ 50 | -------------------------------------------------------------------------------- /src/syscalls/system.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include /* for SYS_accept and others */ 5 | 6 | /* Public Headers */ 7 | #include "qthread/qt_syscalls.h" 8 | 9 | /* Internal Headers */ 10 | #include "qt_asserts.h" 11 | #include "qt_io.h" 12 | #include "qt_qthread_mgmt.h" 13 | #include "qthread_innards.h" /* for qlib */ 14 | 15 | int qt_system(char const *command) { 16 | qthread_t *me = qthread_internal_self(); 17 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 18 | int ret; 19 | 20 | assert(job); 21 | job->next = NULL; 22 | job->thread = me; 23 | job->op = SYSTEM; 24 | job->args[0] = (uintptr_t)command; 25 | 26 | assert(me->rdata); 27 | 28 | me->rdata->blockedon.io = job; 29 | atomic_store_explicit( 30 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 31 | qthread_back_to_master(me); 32 | ret = job->ret; 33 | errno = job->err; 34 | FREE_SYSCALLJOB(job); 35 | return ret; 36 | } 37 | 38 | /* vim:set expandtab: */ 39 | -------------------------------------------------------------------------------- /src/syscalls/user_defined.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include 5 | #include 6 | #include 7 | 8 | #include /* for SYS_accept and others */ 9 | 10 | /* Internal Headers */ 11 | #include "qt_asserts.h" 12 | #include "qt_io.h" 13 | #include "qt_qthread_mgmt.h" 14 | #include "qthread_innards.h" /* for qlib */ 15 | 16 | extern TLS_DECL(qthread_t *, IO_task_struct); 17 | 18 | void API_FUNC qt_begin_blocking_action(void) { 19 | qthread_t *me; 20 | 21 | if ((qlib != NULL) && ((me = qthread_internal_self()) != NULL)) { 22 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 23 | 24 | assert(job); 25 | job->next = NULL; 26 | job->thread = me; 27 | job->op = USER_DEFINED; 28 | 29 | assert(me->rdata); 30 | 31 | me->rdata->blockedon.io = job; 32 | atomic_store_explicit( 33 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 34 | qthread_back_to_master(me); 35 | /* ...and I wake up in a dedicated pthread! */ 36 | } 37 | } 38 | 39 | void API_FUNC qt_end_blocking_action(void) { 40 | qthread_t *me = TLS_GET(IO_task_struct); 41 | 42 | if ((qlib != NULL) && (me != NULL)) { 43 | assert(me != NULL); 44 | qthread_back_to_master(me); 45 | } 46 | } 47 | 48 | /* vim:set expandtab: */ 49 | -------------------------------------------------------------------------------- /src/syscalls/wait4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include /* for SYS_accept and others */ 5 | #include 6 | 7 | /* Public Headers */ 8 | #include "qthread/qt_syscalls.h" 9 | 10 | /* Internal Headers */ 11 | #include "qt_asserts.h" 12 | #include "qt_io.h" 13 | #include "qt_qthread_mgmt.h" 14 | #include "qthread_innards.h" /* for qlib */ 15 | 16 | pid_t qt_wait4(pid_t pid, int *stat_loc, int options, struct rusage *rusage) { 17 | qthread_t *me = qthread_internal_self(); 18 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 19 | pid_t ret; 20 | 21 | assert(job); 22 | job->next = NULL; 23 | job->thread = me; 24 | job->op = WAIT4; 25 | memcpy(&job->args[0], &pid, sizeof(pid_t)); 26 | job->args[1] = (uintptr_t)stat_loc; 27 | memcpy(&job->args[2], &options, sizeof(int)); 28 | job->args[3] = (uintptr_t)rusage; 29 | 30 | assert(me->rdata); 31 | 32 | me->rdata->blockedon.io = job; 33 | atomic_store_explicit( 34 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 35 | qthread_back_to_master(me); 36 | ret = job->ret; 37 | errno = job->err; 38 | FREE_SYSCALLJOB(job); 39 | return ret; 40 | } 41 | 42 | /* vim:set expandtab: */ 43 | -------------------------------------------------------------------------------- /src/syscalls/write.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* System Headers */ 4 | #include 5 | 6 | #include /* for SYS_accept and others */ 7 | #include 8 | 9 | /* Public Headers */ 10 | #include "qthread/qt_syscalls.h" 11 | 12 | /* Internal Headers */ 13 | #include "qt_asserts.h" 14 | #include "qt_io.h" 15 | #include "qt_qthread_mgmt.h" 16 | #include "qthread_innards.h" /* for qlib */ 17 | 18 | ssize_t qt_write(int filedes, void const *buf, size_t nbyte) { 19 | qthread_t *me = qthread_internal_self(); 20 | qt_blocking_queue_node_t *job = ALLOC_SYSCALLJOB(); 21 | ssize_t ret; 22 | 23 | assert(job); 24 | job->next = NULL; 25 | job->thread = me; 26 | job->op = WRITE; 27 | memcpy(&job->args[0], &filedes, sizeof(int)); 28 | job->args[1] = (uintptr_t)buf; 29 | memcpy(&job->args[2], &nbyte, sizeof(size_t)); 30 | 31 | assert(me->rdata); 32 | 33 | me->rdata->blockedon.io = job; 34 | atomic_store_explicit( 35 | &me->thread_state, QTHREAD_STATE_SYSCALL, memory_order_relaxed); 36 | qthread_back_to_master(me); 37 | ret = job->ret; 38 | errno = job->err; 39 | FREE_SYSCALLJOB(job); 40 | return ret; 41 | } 42 | 43 | /* vim:set expandtab: */ 44 | -------------------------------------------------------------------------------- /src/touch.c: -------------------------------------------------------------------------------- 1 | /* Internal Headers */ 2 | #include "qt_qthread_mgmt.h" /* for qthread_internal_self() */ 3 | #include "qt_shepherd_innards.h" 4 | #include "qt_threadqueues.h" 5 | #include "qt_touch.h" 6 | 7 | void qthread_run_needed_task(syncvar_t *value) { 8 | qthread_shepherd_t *shep = qthread_internal_getshep(); 9 | qthread_t *orig_t = qthread_internal_self(); 10 | 11 | if (qt_threadqueue_dequeue_specific(shep->ready, value)) { 12 | // switch to task and run -- else missing and return 13 | qthread_back_to_master(orig_t); 14 | } 15 | } 16 | 17 | /* vim:set expandtab: */ 18 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_STANDARD 11) 2 | 3 | set(QTHREADS_BUILD_TESTS ON CACHE BOOL "Whether or not to build the qthreads tests.") 4 | 5 | if (${QTHREADS_BUILD_TESTS}) 6 | include_directories("." "utils/rng") 7 | 8 | add_subdirectory(utils/rng) 9 | 10 | function(qthreads_test name) 11 | add_executable(${name} "${name}.c") 12 | target_link_libraries(${name} qthread) 13 | target_link_libraries(${name} qthreads_test_rng) 14 | target_link_libraries(${name} m) 15 | add_test(NAME ${name} COMMAND ${name} ${ARGN}) 16 | set_property(TEST ${name} PROPERTY ENVIRONMENT "QT_NUM_SHEPHERDS=2;QT_NUM_WORKERS_PER_SHEPHERD=1") 17 | set_property(TEST ${name} PROPERTY C_STANDARD "C11") 18 | endfunction() 19 | 20 | function(qthreads_test_cpp name) 21 | add_executable(${name} "${name}.cpp") 22 | target_link_libraries(${name} qthread) 23 | target_link_libraries(${name} qthreads_test_rng) 24 | target_link_libraries(${name} m) 25 | add_test(NAME ${name} COMMAND ${name} ${ARGN}) 26 | set_property(TEST ${name} PROPERTY ENVIRONMENT "QT_NUM_SHEPHERDS=2;QT_NUM_WORKERS_PER_SHEPHERD=1") 27 | set_property(TEST ${name} PROPERTY C_STANDARD "C11") 28 | endfunction() 29 | 30 | add_subdirectory(basics) 31 | add_subdirectory(features) 32 | add_subdirectory(internal) 33 | add_subdirectory(stress) 34 | endif() 35 | -------------------------------------------------------------------------------- /test/basics/.gitignore: -------------------------------------------------------------------------------- 1 | aligned_prodcons 2 | aligned_purge_wakes 3 | aligned_readXX_basic 4 | aligned_purge_basic 5 | aligned_writeFF_basic 6 | aligned_writeFF_waits 7 | arbitrary_blocking_operation 8 | external_fork 9 | external_syncvar 10 | hello_world 11 | hello_world_multi 12 | performance 13 | qalloc 14 | qthread_cacheline 15 | qthread_cas 16 | qthread_dincr 17 | qthread_disable_shepherd 18 | qthread_fincr 19 | qthread_fork_precond 20 | qthread_fp 21 | qthread_fp_double 22 | qthread_id 23 | qthread_incr 24 | qthread_migrate_to 25 | qthread_readstate 26 | qthread_stackleft 27 | qthread_timer_wait 28 | qtimer 29 | queue 30 | read 31 | reinitialization 32 | sinc 33 | sinc_null 34 | sinc_workers 35 | syncvar_prodcons 36 | tasklocal_data 37 | tasklocal_data_no_argcopy 38 | tasklocal_data_no_default 39 | test_subteams 40 | test_teams 41 | *.core 42 | -------------------------------------------------------------------------------- /test/basics/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | qthreads_test(hello_world) 2 | qthreads_test(aligned_prodcons) 3 | qthreads_test(aligned_readXX_basic) 4 | qthreads_test(aligned_purge_basic) 5 | qthreads_test(aligned_purge_wakes) 6 | qthreads_test(aligned_writeFF_basic) 7 | qthreads_test(aligned_writeFF_waits) 8 | qthreads_test(hello_world_multi) 9 | qthreads_test(syncvar_prodcons) 10 | qthreads_test(reinitialization) 11 | qthreads_test(qthread_cas) 12 | qthreads_test(qthread_cacheline) 13 | qthreads_test(qthread_readstate) 14 | qthreads_test(qthread_id) 15 | qthreads_test(qthread_incr) 16 | qthreads_test(qthread_fincr) 17 | qthreads_test(qthread_dincr) 18 | qthreads_test(qthread_stackleft) 19 | qthreads_test(qtimer) 20 | qthreads_test(qalloc) 21 | qthreads_test(queue) 22 | qthreads_test(arbitrary_blocking_operation) 23 | qthreads_test(sinc_null) 24 | qthreads_test(sinc_workers) 25 | qthreads_test(sinc) 26 | qthreads_test(tasklocal_data) 27 | qthreads_test(tasklocal_data_no_default) 28 | qthreads_test(tasklocal_data_no_argcopy) 29 | qthreads_test(external_fork) 30 | qthreads_test(external_syncvar) 31 | qthreads_test(read) 32 | qthreads_test(test_teams) 33 | qthreads_test(test_subteams) 34 | qthreads_test(qthread_fork_precond) 35 | qthreads_test(qthread_migrate_to) 36 | qthreads_test(qthread_disable_shepherd) 37 | qthreads_test(qthread_timer_wait) 38 | qthreads_test(qthread_fp) 39 | qthreads_test(qthread_fp_double) 40 | -------------------------------------------------------------------------------- /test/basics/external_syncvar.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Instructions: 3 | * 1) gcc -o main main.c -lpthread -lqthread 4 | * 2) ./main 5 | * 6 | * Credit to Sam 7 | * 8 | */ 9 | #include "argparsing.h" 10 | #include "qthread/qthread.h" 11 | #include 12 | #include 13 | 14 | syncvar_t x = SYNCVAR_STATIC_EMPTY_INITIALIZER; 15 | uint64_t i = 1; 16 | 17 | static void *pthread_routine(void *arg) { 18 | qthread_syncvar_writeEF_const(&x, 1); 19 | return NULL; 20 | } 21 | 22 | int main(void) { 23 | pthread_t thread; 24 | uint64_t readout = 0; 25 | 26 | CHECK_VERBOSE(); 27 | 28 | qthread_initialize(); 29 | 30 | pthread_create(&thread, NULL, pthread_routine, NULL); 31 | 32 | qthread_syncvar_readFE(&readout, &x); 33 | iprintf("found readout = %lu\n", (unsigned long)readout); 34 | 35 | return pthread_join(thread, NULL); 36 | } 37 | 38 | /* vim:set expandtab: */ 39 | -------------------------------------------------------------------------------- /test/basics/hello_world.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static aligned_t greeter(void *arg) { 8 | iprintf("Hello World! My input argument was %lu\n", 9 | (unsigned long)(uintptr_t)arg); 10 | 11 | return 0; 12 | } 13 | 14 | int main(int argc, char *argv[]) { 15 | aligned_t return_value = 0; 16 | int status; 17 | 18 | CHECK_VERBOSE(); // part of the testing harness; toggles iprintf() output 19 | 20 | status = qthread_initialize(); 21 | test_check(status == QTHREAD_SUCCESS); 22 | 23 | iprintf("%i shepherds...\n", qthread_num_shepherds()); 24 | iprintf(" %i threads total\n", qthread_num_workers()); 25 | 26 | status = qthread_fork(greeter, NULL, &return_value); 27 | test_check(status == QTHREAD_SUCCESS); 28 | 29 | int ret = qthread_readFF(NULL, &return_value); 30 | test_check(ret == QTHREAD_SUCCESS); 31 | 32 | iprintf("greeter returned %lu\n", (unsigned long)return_value); 33 | 34 | return EXIT_SUCCESS; 35 | } 36 | 37 | /* vim:set expandtab */ 38 | -------------------------------------------------------------------------------- /test/basics/hello_world_multi.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static aligned_t greeter(void *arg) { 8 | iprintf("Hello World! This is thread %i, running on shepherd %i, worker %i\n", 9 | qthread_id(), 10 | qthread_shep(), 11 | qthread_worker(NULL)); 12 | 13 | return 0; 14 | } 15 | 16 | int main(int argc, char *argv[]) { 17 | long spawn = 0; 18 | aligned_t *rets = NULL; 19 | 20 | test_check(qthread_initialize() == 0); 21 | 22 | CHECK_VERBOSE(); 23 | spawn = qthread_num_workers() * 2; 24 | NUMARG(spawn, "THREADS"); 25 | 26 | iprintf("%i shepherds...\n", qthread_num_shepherds()); 27 | iprintf(" %i threads total\n", qthread_num_workers()); 28 | 29 | rets = malloc(sizeof(aligned_t) * spawn); 30 | test_check(rets != NULL); 31 | 32 | for (long i = 0; i < spawn; i++) { 33 | int ret = qthread_fork(greeter, NULL, rets + i); 34 | test_check(ret == QTHREAD_SUCCESS); 35 | } 36 | 37 | for (long i = 0; i < spawn; i++) { 38 | int ret = qthread_readFF(NULL, rets + i); 39 | test_check(ret == QTHREAD_SUCCESS); 40 | } 41 | 42 | free(rets); 43 | 44 | return EXIT_SUCCESS; 45 | } 46 | 47 | /* vim:set expandtab */ 48 | -------------------------------------------------------------------------------- /test/basics/qthread_cacheline.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *argv[]) { 9 | int cacheline = 0; 10 | 11 | qthread_initialize(); 12 | cacheline = qthread_cacheline(); 13 | CHECK_VERBOSE(); 14 | iprintf("%i bytes\n", cacheline); 15 | test_check(cacheline > 0); 16 | return 0; 17 | } 18 | 19 | /* vim:set expandtab */ 20 | -------------------------------------------------------------------------------- /test/benchmarks/.gitignore: -------------------------------------------------------------------------------- 1 | fib_qthreads 2 | spawn_parallel_qthreads 3 | spawn_sequential_qthreads 4 | time_allpairs 5 | time_chain_bench 6 | time_chain_bench_pthread 7 | time_cncthr_bench 8 | time_cncthr_bench_pthread 9 | time_chpl_spawn 10 | time_eager_future 11 | time_febs 12 | time_febs_graph_test 13 | time_febs_stream_test 14 | time_fib 15 | time_fib2 16 | time_gcd 17 | time_halo_swap_all 18 | time_incr_bench 19 | time_incr_bench_pthread 20 | time_increments 21 | time_lul_bench 22 | time_lul_bench_pthread 23 | time_mutex_bench 24 | time_mutex_bench_pthread 25 | time_prodcons_comm 26 | time_producerconsumer 27 | time_qarray 28 | time_qarray_sizes 29 | time_qdqueue 30 | time_qdqueue_sizes 31 | time_qlfqueue 32 | time_qpool 33 | time_qt_loopaccums 34 | time_qt_loops 35 | time_qutil_qsort 36 | time_spin_bench 37 | time_spin_bench_pthread 38 | time_stencil_bsp 39 | time_stencil_feb 40 | time_stencil_pre 41 | time_syncvar_producerconsumer 42 | time_task_spawn 43 | time_thrcrt_bench 44 | time_thrcrt_bench_pthread 45 | time_threading 46 | time_thread_ring 47 | time_uts_aligned 48 | time_uts_donecount 49 | time_uts_donecount2 50 | time_uts_donecount3 51 | time_uts_sinc 52 | time_uts_syncvar 53 | time_wavefront 54 | uts_qthreads 55 | -------------------------------------------------------------------------------- /test/benchmarks/finepoints/partSendPrototype/mpiPart.h: -------------------------------------------------------------------------------- 1 | 2 | int MPI_Partitioned_Send_create(void const *buf, 3 | int count, 4 | MPI_Datatype datatype, 5 | int numThreads, 6 | int dest, 7 | int tag, 8 | MPI_Comm comm, 9 | MPI_Request *request); 10 | int MPI_Partitioned_Recv_create(void *buf, 11 | int count, 12 | MPI_Datatype datatype, 13 | int source, 14 | int tag, 15 | MPI_Comm comm, 16 | MPI_Request *request); 17 | 18 | int MPI_Partitioned_Add_to_buffer(MPI_Request *, 19 | void const *send_buf, 20 | int count, 21 | MPI_Datatype); 22 | 23 | int MPI_Partitioned_free(MPI_Request *); 24 | 25 | int MPI_Wait_part(MPI_Request *request, MPI_Status *status); 26 | 27 | int MPI_Start_part(MPI_Request *request); 28 | -------------------------------------------------------------------------------- /test/benchmarks/generic/time_chpl_spawn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | static aligned_t decTask(void *arg) { 8 | aligned_t *doneCount = (aligned_t *)arg; 9 | qthread_incr(doneCount, -1); 10 | 11 | return 0; 12 | } 13 | 14 | static void qtChplLikeTaskSpawn(int64_t trials, int64_t numTasks) { 15 | int i, j; 16 | 17 | for (i = 0; i < trials; i++) { 18 | aligned_t doneCount; 19 | doneCount = 0; 20 | qthread_incr(&doneCount, numTasks); 21 | for (j = 0; j < numTasks; j++) { 22 | qthread_fork(decTask, &(doneCount), NULL); 23 | } 24 | while (qthread_incr(&doneCount, 0)) { qthread_yield(); } 25 | } 26 | } 27 | 28 | static void emptyFunction(size_t start, size_t stop, void *arg) {} 29 | 30 | static void qtLoopTaskSpawn(int64_t trials, int64_t numTasks) { 31 | int i; 32 | for (i = 0; i < trials; i++) { qt_loop_dc(0, numTasks, emptyFunction, NULL); } 33 | } 34 | 35 | int main() { 36 | qthread_initialize(); 37 | int64_t numTasks = qthread_num_workers(); 38 | int64_t numTrials = 500000; 39 | 40 | qtimer_t t = qtimer_create(); 41 | qtimer_start(t); 42 | { 43 | qtLoopTaskSpawn(numTrials, numTasks); 44 | // qtChplLikeTaskSpawn(numTrials, numTasks); 45 | } 46 | qtimer_stop(t); 47 | printf("Elapsed time for %lld workers: %f\n", numTasks, qtimer_secs(t)); 48 | } 49 | -------------------------------------------------------------------------------- /test/benchmarks/mantevo/hpccg/.gitignore: -------------------------------------------------------------------------------- 1 | hpccg 2 | -------------------------------------------------------------------------------- /test/benchmarks/mantevo/hpccg/VERSION: -------------------------------------------------------------------------------- 1 | Version 0.1 (Initial version) 2 | Version 0.2: 3 | - Fixed bugs related to turning MPI compilation off. 4 | - Added more text to README to improve understanding. 5 | - Added new Makfile.x86linux.gcc for non-opteron systems. 6 | - Made MPI_Wtime the default timer when in MPI mode. 7 | Version 0.3: 8 | - Fixed a performance bug in make_local_matrix.cpp that was 9 | very noticeable when the fraction of off-processor grid 10 | points was large. 11 | Version 0.4: 12 | - Made total_nnz a "long long" so that MFLOP numbers were valid 13 | when the nonzero count is more than 2^31. 14 | Version 0.5: 15 | - Added timing for Allreduce calls in MPI mode, printing min/max/avg times. 16 | - Set the solver tolerance to zero to make all solves take max_iter iterations. 17 | - Changed accumulator to a local variable for ddot. It seems to help dual-core 18 | performance. 19 | -------------------------------------------------------------------------------- /test/benchmarks/mantevo/hpccg/loop_defines.h: -------------------------------------------------------------------------------- 1 | #ifndef LOOP_DEFINES_H 2 | #define LOOP_DEFINES_H 3 | 4 | #include 5 | 6 | #ifdef USING_QTHREADS 7 | #include 8 | #include 9 | #define LOOP_BEGIN(x, y, b, e) qt_loop_balance((x), (y), [&](size_t b, size_t e) { 10 | #define LOOP_END() \ 11 | }) 12 | #else 13 | #define LOOP_BEGIN(x, y, b, e) \ 14 | const size_t b = (x); \ 15 | const size_t e = (y); 16 | #define LOOP_END() 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /test/benchmarks/mt/time_cilk_task_spawn.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // static aligned_t donecount = 0; 10 | 11 | static aligned_t null_task(void *args_) { return 0; } 12 | 13 | int main(int argc, char *argv[]) { 14 | unsigned long count = 0; 15 | unsigned long i; 16 | int par_fork = 0; 17 | 18 | qtimer_t timer; 19 | double total_time = 0.0; 20 | 21 | CHECK_VERBOSE(); 22 | 23 | NUMARG(count, "MT_COUNT"); 24 | NUMARG(par_fork, "MT_PAR_FORK"); 25 | assert(0 != count); 26 | 27 | timer = qtimer_create(); 28 | 29 | if (par_fork) { 30 | qtimer_start(timer); 31 | 32 | _Cilk_for(i = 0; i < count; i++) { _Cilk_spawn null_task(NULL); } 33 | } else { 34 | qtimer_start(timer); 35 | 36 | for (i = 0; i < count; i++) { _Cilk_spawn null_task(NULL); } 37 | } 38 | _Cilk_sync; 39 | 40 | qtimer_stop(timer); 41 | 42 | total_time = qtimer_secs(timer); 43 | 44 | qtimer_destroy(timer); 45 | 46 | printf("%lu %lu %f\n", 47 | (unsigned long)__cilkrts_get_nworkers(), 48 | (unsigned long)count, 49 | total_time); 50 | 51 | return 0; 52 | } 53 | 54 | /* vim:set expandtab */ 55 | -------------------------------------------------------------------------------- /test/benchmarks/mt/time_task_spawn.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static aligned_t donecount = 0; 9 | 10 | static aligned_t null_task(void *args_) { return qthread_incr(&donecount, 1); } 11 | 12 | static void par_null_task(size_t start, size_t stop, void *args_) {} 13 | 14 | int main(int argc, char *argv[]) { 15 | uint64_t count = 1048576; 16 | int par_fork = 0; 17 | 18 | qtimer_t timer; 19 | double total_time = 0.0; 20 | 21 | CHECK_VERBOSE(); 22 | 23 | NUMARG(count, "MT_COUNT"); 24 | NUMARG(par_fork, "MT_PAR_FORK"); 25 | assert(0 != count); 26 | 27 | assert(qthread_initialize() == 0); 28 | 29 | timer = qtimer_create(); 30 | 31 | if (par_fork) { 32 | qtimer_start(timer); 33 | 34 | qt_loop(0, count, par_null_task, NULL); 35 | } else { 36 | qtimer_start(timer); 37 | 38 | for (uint64_t i = 0; i < count; i++) qthread_fork(null_task, NULL, NULL); 39 | do { qthread_yield(); } while (donecount != count); 40 | } 41 | 42 | qtimer_stop(timer); 43 | 44 | total_time = qtimer_secs(timer); 45 | 46 | qtimer_destroy(timer); 47 | 48 | printf("%lu %lu %f\n", 49 | (unsigned long)qthread_num_workers(), 50 | (unsigned long)count, 51 | total_time); 52 | 53 | return 0; 54 | } 55 | 56 | /* vim:set expandtab */ 57 | -------------------------------------------------------------------------------- /test/benchmarks/mtaap08/time_cncthr_bench.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define NUM_THREADS 1000000 11 | 12 | static aligned_t qincr(void *arg) { return 0; } 13 | 14 | int main(int argc, char *argv[]) { 15 | aligned_t rets[NUM_THREADS]; 16 | qtimer_t timer = qtimer_create(); 17 | double cumulative_time = 0.0; 18 | 19 | if (qthread_initialize() != QTHREAD_SUCCESS) { 20 | fprintf(stderr, "qthread library could not be initialized!\n"); 21 | exit(EXIT_FAILURE); 22 | } 23 | CHECK_VERBOSE(); 24 | 25 | for (int iteration = 0; iteration < 10; iteration++) { 26 | qtimer_start(timer); 27 | for (int i = 0; i < NUM_THREADS; i++) { 28 | qthread_fork(qincr, NULL, &(rets[i])); 29 | } 30 | for (int i = 0; i < NUM_THREADS; i++) { qthread_readFF(NULL, &(rets[i])); } 31 | qtimer_stop(timer); 32 | iprintf("\ttest iteration %i: %f secs\n", iteration, qtimer_secs(timer)); 33 | cumulative_time += qtimer_secs(timer); 34 | } 35 | printf("qthread time: %f\n", cumulative_time / 10.0); 36 | 37 | return 0; 38 | } 39 | 40 | /* vim:set expandtab */ 41 | -------------------------------------------------------------------------------- /test/benchmarks/mtaap08/time_cncthr_bench_pthread.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define NUM_THREADS 1000000 11 | 12 | static void *qincr(void *arg) { return NULL; } 13 | 14 | int main(int argc, char *argv[]) { 15 | pthread_t rets[NUM_THREADS]; 16 | qtimer_t timer = qtimer_create(); 17 | double cumulative_time = 0.0; 18 | size_t counter; 19 | 20 | CHECK_VERBOSE(); 21 | 22 | for (int iteration = 0; iteration < 10; iteration++) { 23 | qtimer_start(timer); 24 | for (int i = 0; i < NUM_THREADS; i++) { 25 | pthread_create(&(rets[i]), NULL, qincr, &counter); 26 | } 27 | for (int i = 0; i < NUM_THREADS; i++) { pthread_join(rets[i], NULL); } 28 | qtimer_stop(timer); 29 | iprintf("\ttest iteration %i: %f secs\n", iteration, qtimer_secs(timer)); 30 | cumulative_time += qtimer_secs(timer); 31 | } 32 | printf("pthread time: %f\n", cumulative_time / 10.0); 33 | 34 | return 0; 35 | } 36 | 37 | /* vim:set expandtab */ 38 | -------------------------------------------------------------------------------- /test/benchmarks/mtaap08/time_lul_bench_pthread.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #define NUM_THREADS 1000 11 | #define PER_THREAD_INCR 10000 12 | 13 | aligned_t counter = 0; 14 | pthread_mutex_t counter_lock; 15 | 16 | static void *qincr(void *arg) { 17 | size_t incrs; 18 | 19 | for (incrs = 0; incrs < PER_THREAD_INCR; incrs++) { 20 | pthread_mutex_lock(&counter_lock); 21 | pthread_mutex_unlock(&counter_lock); 22 | } 23 | return NULL; 24 | } 25 | 26 | int main(int argc, char *argv[]) { 27 | pthread_t rets[NUM_THREADS]; 28 | qtimer_t timer = qtimer_create(); 29 | double cumulative_time = 0.0; 30 | 31 | CHECK_VERBOSE(); 32 | 33 | for (int iteration = 0; iteration < 10; iteration++) { 34 | qtimer_start(timer); 35 | for (int i = 0; i < NUM_THREADS; i++) { 36 | pthread_create(&(rets[i]), NULL, qincr, &counter); 37 | } 38 | for (int i = 0; i < NUM_THREADS; i++) { pthread_join(rets[i], NULL); } 39 | qtimer_stop(timer); 40 | iprintf("\ttest iteration %i: %f secs\n", iteration, qtimer_secs(timer)); 41 | cumulative_time += qtimer_secs(timer); 42 | } 43 | printf("pthread time: %f\n", cumulative_time / 10.0); 44 | 45 | return 0; 46 | } 47 | 48 | /* vim:set expandtab */ 49 | -------------------------------------------------------------------------------- /test/benchmarks/sc12/spawn_parallel_cilk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define SILENT_ARGPARSING 9 | #include "argparsing.h" 10 | #include "log.h" 11 | 12 | // static aligned_t donecount = 0; 13 | 14 | static aligned_t null_task(void *args_) { return 0; } 15 | 16 | int main(int argc, char *argv[]) { 17 | unsigned long count = 1048576; 18 | unsigned long i; 19 | 20 | qtimer_t timer; 21 | double total_time = 0.0; 22 | 23 | CHECK_VERBOSE(); 24 | 25 | NUMARG(count, "MT_COUNT"); 26 | assert(0 != count); 27 | 28 | timer = qtimer_create(); 29 | qtimer_start(timer); 30 | _Cilk_for(i = 0; i < count; i++) { _Cilk_spawn null_task(NULL); } 31 | _Cilk_sync; 32 | qtimer_stop(timer); 33 | 34 | total_time = qtimer_secs(timer); 35 | 36 | qtimer_destroy(timer); 37 | 38 | LOG_SPAWN_PARALLEL_YAML(count, total_time) 39 | LOG_ENV_CILK_YAML() 40 | 41 | return 0; 42 | } 43 | 44 | /* vim:set expandtab */ 45 | -------------------------------------------------------------------------------- /test/benchmarks/sc12/spawn_parallel_omp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #define SILENT_ARGPARSING 9 | #include "argparsing.h" 10 | #include "log.h" 11 | 12 | static aligned_t null_task(void *args_) { return 0; } 13 | 14 | int main(int argc, char *argv[]) { 15 | uint64_t count = 1048576; 16 | unsigned long threads = 1; 17 | 18 | qtimer_t timer; 19 | double total_time = 0.0; 20 | 21 | CHECK_VERBOSE(); 22 | 23 | NUMARG(count, "MT_COUNT"); 24 | assert(0 != count); 25 | 26 | #pragma omp parallel 27 | #pragma omp single 28 | { 29 | timer = qtimer_create(); 30 | threads = omp_get_num_threads(); 31 | 32 | qtimer_start(timer); 33 | #pragma omp parallel for 34 | for (uint64_t i = 0; i < count; i++) { 35 | #pragma omp task untied 36 | null_task(NULL); 37 | } 38 | #pragma omp taskwait 39 | qtimer_stop(timer); 40 | } 41 | 42 | total_time = qtimer_secs(timer); 43 | 44 | qtimer_destroy(timer); 45 | 46 | LOG_SPAWN_PARALLEL_YAML(count, total_time) 47 | LOG_ENV_OMP_YAML(threads) 48 | 49 | return 0; 50 | } 51 | 52 | /* vim:set expandtab */ 53 | -------------------------------------------------------------------------------- /test/benchmarks/sc12/spawn_sequential_cilk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define SILENT_ARGPARSING 9 | #include "argparsing.h" 10 | #include "log.h" 11 | 12 | // static aligned_t donecount = 0; 13 | 14 | static aligned_t null_task(void *args_) { return 0; } 15 | 16 | int main(int argc, char *argv[]) { 17 | unsigned long count = 1048576; 18 | unsigned long i; 19 | 20 | qtimer_t timer; 21 | double total_time = 0.0; 22 | 23 | CHECK_VERBOSE(); 24 | 25 | NUMARG(count, "MT_COUNT"); 26 | assert(0 != count); 27 | 28 | timer = qtimer_create(); 29 | 30 | qtimer_start(timer); 31 | for (i = 0; i < count; i++) { _Cilk_spawn null_task(NULL); } 32 | _Cilk_sync; 33 | 34 | qtimer_stop(timer); 35 | 36 | total_time = qtimer_secs(timer); 37 | 38 | qtimer_destroy(timer); 39 | 40 | LOG_SPAWN_SEQUENTIAL_YAML(count, total_time) 41 | LOG_ENV_CILK_YAML() 42 | 43 | return 0; 44 | } 45 | 46 | /* vim:set expandtab */ 47 | -------------------------------------------------------------------------------- /test/benchmarks/sc12/spawn_sequential_omp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #define SILENT_ARGPARSING 9 | #include "argparsing.h" 10 | #include "log.h" 11 | 12 | static aligned_t null_task(void *args_) { return 0; } 13 | 14 | int main(int argc, char *argv[]) { 15 | uint64_t count = 1048576; 16 | unsigned long threads = 1; 17 | 18 | qtimer_t timer; 19 | double total_time = 0.0; 20 | 21 | CHECK_VERBOSE(); 22 | 23 | NUMARG(count, "MT_COUNT"); 24 | assert(0 != count); 25 | 26 | #pragma omp parallel 27 | #pragma omp single 28 | { 29 | timer = qtimer_create(); 30 | threads = omp_get_num_threads(); 31 | 32 | qtimer_start(timer); 33 | #pragma omp task untied 34 | for (uint64_t i = 0; i < count; i++) { 35 | #pragma omp task untied 36 | null_task(NULL); 37 | } 38 | #pragma omp taskwait 39 | qtimer_stop(timer); 40 | } 41 | 42 | total_time = qtimer_secs(timer); 43 | 44 | qtimer_destroy(timer); 45 | 46 | LOG_SPAWN_SEQUENTIAL_YAML(count, total_time) 47 | LOG_ENV_OMP_YAML(threads) 48 | 49 | return 0; 50 | } 51 | 52 | /* vim:set expandtab */ 53 | -------------------------------------------------------------------------------- /test/benchmarks/sc12/spawn_sequential_qthreads.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define SILENT_ARGPARSING 8 | #include "argparsing.h" 9 | #include "log.h" 10 | 11 | static aligned_t donecount = 0; 12 | 13 | static aligned_t null_task(void *args_) { return qthread_incr(&donecount, 1); } 14 | 15 | int main(int argc, char *argv[]) { 16 | uint64_t count = 1048576; 17 | 18 | qtimer_t timer; 19 | double total_time = 0.0; 20 | 21 | CHECK_VERBOSE(); 22 | 23 | NUMARG(count, "MT_COUNT"); 24 | assert(0 != count); 25 | 26 | assert(qthread_initialize() == 0); 27 | 28 | timer = qtimer_create(); 29 | 30 | qtimer_start(timer); 31 | for (uint64_t i = 0; i < count; i++) { 32 | qthread_spawn( 33 | null_task, NULL, 0, NULL, 0, NULL, NO_SHEPHERD, QTHREAD_SPAWN_SIMPLE); 34 | } 35 | do { qthread_yield(); } while (donecount != count); 36 | qtimer_stop(timer); 37 | 38 | total_time = qtimer_secs(timer); 39 | 40 | qtimer_destroy(timer); 41 | 42 | LOG_SPAWN_SEQUENTIAL_YAML(count, total_time) 43 | LOG_ENV_QTHREADS_YAML() 44 | 45 | return 0; 46 | } 47 | 48 | /* vim:set expandtab */ 49 | -------------------------------------------------------------------------------- /test/benchmarks/sc12/uts_tree_parameters.sh: -------------------------------------------------------------------------------- 1 | ################################################## 2 | # Unbalanced Tree Search v2.1 - Sample Trees # 3 | # Based on the implementation available at # 4 | # http://sourceforge.net/projects/uts-benchmark # 5 | ################################################## 6 | 7 | export UTS_T3="UTS_DATASET=UTS_T3 UTS_TREE_TYPE=0 UTS_BF_0=2000 UTS_NON_LEAF_PROB=0.124875 UTS_NON_LEAF_NUM=8 UTS_ROOT_SEED=42" 8 | export UTS_T3L="UTS_DATASET=UTS_T3L UTS_TREE_TYPE=0 UTS_BF_0=2000 UTS_NON_LEAF_PROB=0.200014 UTS_NON_LEAF_NUM=5 UTS_ROOT_SEED=7" 9 | export UTS_T3XXL="UTS_DATASET=UTS_T3XXL UTS_TREE_TYPE=0 UTS_BF_0=2000 UTS_NON_LEAF_PROB=0.499995 UTS_NON_LEAF_NUM=2 UTS_ROOT_SEED=316" 10 | export UTS_T2XXL="UTS_DATASET=UTS_T2XXL UTS_TREE_TYPE=0 UTS_BF_0=2000 UTS_NON_LEAF_PROB=0.499999995 UTS_NON_LEAF_NUM=2 UTS_ROOT_SEED=0" 11 | export UTS_T2WL="UTS_DATASET=UTS_T2WL UTS_TREE_TYPE=0 UTS_BF_0=2000 UTS_NON_LEAF_PROB=0.4999999995 UTS_NON_LEAF_NUM=2 UTS_ROOT_SEED=559" 12 | export UTS_T3WL="UTS_DATASET=UTS_T3WL UTS_TREE_TYPE=0 UTS_BF_0=2000 UTS_NON_LEAF_PROB=0.4999995 UTS_NON_LEAF_NUM=2 UTS_ROOT_SEED=559" 13 | -------------------------------------------------------------------------------- /test/features/.gitignore: -------------------------------------------------------------------------------- 1 | allpairs 2 | barrier 3 | cxx_futurelib 4 | cxx_qt_loop 5 | cxx_qt_loop_balance 6 | qarray 7 | qarray_accum 8 | qdqueue 9 | qlfqueue 10 | qloop_utils 11 | qpool 12 | qswsrqueue 13 | qt_dictionary 14 | qt_loop 15 | qt_loop_balance 16 | qt_loop_balance_sinc 17 | qt_loop_balance_simple 18 | qt_loop_queue 19 | qt_loop_simple 20 | qt_loop_sinc 21 | qutil 22 | qutil_qsort 23 | subteams 24 | -------------------------------------------------------------------------------- /test/features/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | qthreads_test(qt_loop) 2 | qthreads_test(qt_loop_simple) 3 | qthreads_test(qt_loop_sinc) 4 | qthreads_test(qt_loop_balance) 5 | qthreads_test(qt_loop_balance_simple) 6 | qthreads_test(qt_loop_balance_sinc) 7 | qthreads_test(qt_loop_queue) 8 | qthreads_test(qutil) 9 | qthreads_test(qutil_qsort) 10 | qthreads_test(barrier) 11 | qthreads_test(qloop_utils) 12 | qthreads_test(qarray) 13 | qthreads_test(qarray_accum) 14 | qthreads_test(qpool) 15 | qthreads_test(qlfqueue) 16 | qthreads_test(qswsrqueue) 17 | qthreads_test(qdqueue) 18 | qthreads_test(allpairs) 19 | qthreads_test(subteams) 20 | qthreads_test(qt_dictionary) 21 | qthreads_test_cpp(cxx_qt_loop) 22 | qthreads_test_cpp(cxx_qt_loop_balance) 23 | -------------------------------------------------------------------------------- /test/features/cxx_qt_loop.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "argparsing.h" 6 | 7 | struct test_struct { 8 | test_struct(int _x, int *_answer): x(_x), answer(_answer) {} 9 | 10 | void operator()(int start, int stop) { 11 | iprintf("start: %4d stop: %4d\n", start, stop); 12 | for (int i = start; i < stop; ++i) { answer[i] = x * i; } 13 | } 14 | 15 | int x; 16 | int *answer; 17 | }; 18 | 19 | void test_func() { 20 | int *answer = (int *)malloc(sizeof(int) * 100); 21 | 22 | for (int i = 0; i < 100; ++i) answer[i] = 0; 23 | 24 | qt_loop(0, 100, test_struct(3, answer)); 25 | // qt_loop_future(0, 100, test_struct(3, answer)); 26 | // qt_loop_balance(0, 100, test_struct(3, answer)); 27 | // qt_loop_balance_future(0, 100, test_struct(3, answer)); 28 | 29 | iprintf("\nanswer:"); 30 | for (int i = 0; i < 100; ++i) { 31 | iprintf("%6d", answer[i]); 32 | if (i % 10 == 9) { iprintf("\n "); } 33 | } 34 | iprintf("\n"); 35 | 36 | free(answer); 37 | } 38 | 39 | int main(int argc, char **argv) { 40 | qthread_initialize(); 41 | 42 | CHECK_VERBOSE(); 43 | 44 | test_func(); 45 | 46 | return 0; 47 | } 48 | 49 | /* vim:set expandtab: */ 50 | -------------------------------------------------------------------------------- /test/features/qt_loop.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static _Atomic aligned_t threads = 0; 8 | static aligned_t numincrs = 1024; 9 | 10 | static void sum(size_t const startat, size_t const stopat, void *arg_) { 11 | atomic_fetch_add_explicit(&threads, stopat - startat, memory_order_relaxed); 12 | } 13 | 14 | int main(int argc, char *argv[]) { 15 | test_check(qthread_initialize() == QTHREAD_SUCCESS); 16 | CHECK_VERBOSE(); 17 | NUMARG(numincrs, "NUM_INCRS"); 18 | // future_init(128); 19 | iprintf("%i shepherds\n", qthread_num_shepherds()); 20 | iprintf("%i threads\n", qthread_num_workers()); 21 | 22 | qt_loop(0, numincrs, sum, NULL); 23 | 24 | if (threads != numincrs) { 25 | iprintf("threads == %lu, not %lu\n", 26 | (unsigned long)threads, 27 | (unsigned long)numincrs); 28 | } 29 | test_check(threads == numincrs); 30 | 31 | return 0; 32 | } 33 | 34 | /* vim:set expandtab */ 35 | -------------------------------------------------------------------------------- /test/features/qt_loop_balance.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t threads = 0; 7 | static aligned_t numincrs = 1024; 8 | 9 | static void sum(size_t const startat, size_t const stopat, void *arg_) { 10 | qthread_incr(&threads, stopat - startat); 11 | } 12 | 13 | int main(int argc, char *argv[]) { 14 | test_check(qthread_initialize() == QTHREAD_SUCCESS); 15 | CHECK_VERBOSE(); 16 | NUMARG(numincrs, "NUM_INCRS"); 17 | // future_init(128); 18 | iprintf("%i shepherds\n", qthread_num_shepherds()); 19 | iprintf("%i threads\n", qthread_num_workers()); 20 | 21 | qt_loop_balance(0, numincrs, sum, NULL); 22 | 23 | if (threads != numincrs) { 24 | iprintf("threads == %lu, not %lu\n", 25 | (unsigned long)threads, 26 | (unsigned long)numincrs); 27 | } 28 | test_check(threads == numincrs); 29 | 30 | return 0; 31 | } 32 | 33 | /* vim:set expandtab */ 34 | -------------------------------------------------------------------------------- /test/features/qt_loop_balance_simple.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t threads = 0; 7 | static aligned_t numincrs = 1024; 8 | 9 | static void sum(size_t const startat, size_t const stopat, void *arg_) { 10 | qthread_incr(&threads, stopat - startat); 11 | } 12 | 13 | int main(int argc, char *argv[]) { 14 | test_check(qthread_initialize() == QTHREAD_SUCCESS); 15 | CHECK_VERBOSE(); 16 | NUMARG(numincrs, "NUM_INCRS"); 17 | // future_init(128); 18 | iprintf("%i shepherds\n", qthread_num_shepherds()); 19 | iprintf("%i threads\n", qthread_num_workers()); 20 | 21 | qt_loop_balance_simple(0, numincrs, sum, NULL); 22 | 23 | if (threads != numincrs) { 24 | iprintf("threads == %lu, not %lu\n", 25 | (unsigned long)threads, 26 | (unsigned long)numincrs); 27 | } 28 | test_check(threads == numincrs); 29 | 30 | return 0; 31 | } 32 | 33 | /* vim:set expandtab */ 34 | -------------------------------------------------------------------------------- /test/features/qt_loop_balance_sinc.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t threads = 0; 7 | static aligned_t numincrs = 1024; 8 | 9 | static void sum(size_t const startat, size_t const stopat, void *arg_) { 10 | qthread_incr(&threads, stopat - startat); 11 | } 12 | 13 | int main(int argc, char *argv[]) { 14 | test_check(qthread_initialize() == QTHREAD_SUCCESS); 15 | CHECK_VERBOSE(); 16 | NUMARG(numincrs, "NUM_INCRS"); 17 | // future_init(128); 18 | iprintf("%i shepherds\n", qthread_num_shepherds()); 19 | iprintf("%i threads\n", qthread_num_workers()); 20 | 21 | qt_loop_balance_sinc(0, numincrs, sum, NULL); 22 | 23 | if (threads != numincrs) { 24 | iprintf("threads == %lu, not %lu\n", 25 | (unsigned long)threads, 26 | (unsigned long)numincrs); 27 | } 28 | test_check(threads == numincrs); 29 | 30 | return 0; 31 | } 32 | 33 | /* vim:set expandtab */ 34 | -------------------------------------------------------------------------------- /test/features/qt_loop_simple.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t threads = 0; 7 | static aligned_t numincrs = 1024; 8 | 9 | static void sum(size_t const startat, size_t const stopat, void *arg_) { 10 | qthread_incr(&threads, stopat - startat); 11 | } 12 | 13 | int main(int argc, char *argv[]) { 14 | test_check(qthread_initialize() == QTHREAD_SUCCESS); 15 | CHECK_VERBOSE(); 16 | NUMARG(numincrs, "NUM_INCRS"); 17 | // future_init(128); 18 | iprintf("%i shepherds\n", qthread_num_shepherds()); 19 | iprintf("%i threads\n", qthread_num_workers()); 20 | 21 | qt_loop_simple(0, numincrs, sum, NULL); 22 | 23 | if (threads != numincrs) { 24 | iprintf("threads == %lu, not %lu\n", 25 | (unsigned long)threads, 26 | (unsigned long)numincrs); 27 | } 28 | test_check(threads == numincrs); 29 | 30 | return 0; 31 | } 32 | 33 | /* vim:set expandtab */ 34 | -------------------------------------------------------------------------------- /test/features/qt_loop_sinc.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t threads = 0; 7 | static aligned_t numincrs = 1024; 8 | 9 | static void sum(size_t const startat, size_t const stopat, void *arg_) { 10 | qthread_incr(&threads, stopat - startat); 11 | } 12 | 13 | int main(int argc, char *argv[]) { 14 | test_check(qthread_initialize() == QTHREAD_SUCCESS); 15 | CHECK_VERBOSE(); 16 | NUMARG(numincrs, "NUM_INCRS"); 17 | // future_init(128); 18 | iprintf("%i shepherds\n", qthread_num_shepherds()); 19 | iprintf("%i threads\n", qthread_num_workers()); 20 | 21 | qt_loop_sinc(0, numincrs, sum, NULL); 22 | 23 | if (threads != numincrs) { 24 | iprintf("threads == %lu, not %lu\n", 25 | (unsigned long)threads, 26 | (unsigned long)numincrs); 27 | } 28 | test_check(threads == numincrs); 29 | 30 | return 0; 31 | } 32 | 33 | /* vim:set expandtab */ 34 | -------------------------------------------------------------------------------- /test/internal/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # tests for internal APIs can access internal headers. 2 | include_directories("../../include") 3 | 4 | qthreads_test(threadpool) 5 | -------------------------------------------------------------------------------- /test/internal/threadpool.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include "qt_threadpool.h" 3 | 4 | static int on_thread_test(void *arg) { 5 | printf("hello from thread\n"); 6 | return 0; 7 | } 8 | 9 | int main() { 10 | hw_pool_init(2); 11 | hw_pool_destroy(); 12 | hw_pool_init(2); 13 | hw_pool_run_on_all(&on_thread_test, NULL); 14 | hw_pool_destroy(); 15 | printf("exited successfully\n"); 16 | fflush(stdout); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /test/stress/.gitignore: -------------------------------------------------------------------------------- 1 | feb_prodcons_contended 2 | feb_stream 3 | lock_acq_rel 4 | precond_fib 5 | precond_spawn_simple 6 | subteams_uts 7 | syncvar_prodcons_contended 8 | syncvar_stream 9 | task_spawn 10 | test_spawn_simple 11 | -------------------------------------------------------------------------------- /test/stress/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | qthreads_test(feb_prodcons_contended) 2 | qthreads_test(syncvar_prodcons_contended) 3 | qthreads_test(feb_stream) 4 | qthreads_test(syncvar_stream) 5 | qthreads_test(precond_fib) 6 | qthreads_test(task_spawn) 7 | qthreads_test(test_spawn_simple) 8 | qthreads_test(precond_spawn_simple) 9 | qthreads_test(lock_acq_rel) 10 | qthreads_test(feb_as_fence) 11 | qthreads_test(subteams_uts) 12 | -------------------------------------------------------------------------------- /test/stress/precond_spawn_simple.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t donecount = 0; 7 | 8 | static aligned_t null_task(void *args_) { return qthread_incr(&donecount, 1); } 9 | 10 | int main(int argc, char *argv[]) { 11 | uint64_t count = 524288; // 1048576; 12 | 13 | CHECK_VERBOSE(); 14 | 15 | NUMARG(count, "MT_COUNT"); 16 | test_check(0 != count); 17 | 18 | test_check(qthread_initialize() == 0); 19 | 20 | for (uint64_t i = 0; i < count; i++) { 21 | qthread_fork_precond_simple(null_task, NULL, NULL, 0, NULL); 22 | } 23 | do { 24 | aligned_t tmp = donecount; 25 | qthread_yield(); 26 | if (tmp != donecount) { 27 | iprintf("donecount = %u\n", (unsigned int)donecount); 28 | } 29 | } while (donecount != count); 30 | 31 | return 0; 32 | } 33 | 34 | /* vim:set expandtab */ 35 | -------------------------------------------------------------------------------- /test/stress/task_spawn.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t donecount = 0; 7 | 8 | static aligned_t null_task(void *args_) { return qthread_incr(&donecount, 1); } 9 | 10 | static void par_null_task(size_t start, size_t stop, void *args_) {} 11 | 12 | int main(int argc, char *argv[]) { 13 | uint64_t count = 524288; // 1048576; 14 | 15 | CHECK_VERBOSE(); 16 | 17 | NUMARG(count, "MT_COUNT"); 18 | test_check(0 != count); 19 | 20 | test_check(qthread_initialize() == 0); 21 | 22 | for (uint64_t i = 0; i < count; i++) { qthread_fork(null_task, NULL, NULL); } 23 | do { 24 | aligned_t tmp = donecount; 25 | qthread_yield(); 26 | if (tmp != donecount) { 27 | iprintf( 28 | "donecount = %u, tmp = %u\n", (unsigned int)donecount, (unsigned)tmp); 29 | } 30 | } while (donecount != count); 31 | iprintf("manually spawned and sync'd %u threads\n", (unsigned)count); 32 | 33 | qt_loop(0, count, par_null_task, NULL); 34 | iprintf("automatically spawned and sync'd %u threads\n", (unsigned)count); 35 | 36 | return 0; 37 | } 38 | 39 | /* vim:set expandtab */ 40 | -------------------------------------------------------------------------------- /test/stress/test_spawn_simple.c: -------------------------------------------------------------------------------- 1 | #include "argparsing.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static aligned_t donecount = 0; 7 | 8 | static aligned_t null_task(void *args_) { return qthread_incr(&donecount, 1); } 9 | 10 | int main(int argc, char *argv[]) { 11 | uint64_t count = 524288; // 1048576; 12 | 13 | CHECK_VERBOSE(); 14 | 15 | NUMARG(count, "MT_COUNT"); 16 | test_check(0 != count); 17 | 18 | test_check(qthread_initialize() == 0); 19 | 20 | for (uint64_t i = 0; i < count; i++) { 21 | // qthread_fork_precond_simple(null_task, NULL, NULL, 0, NULL); 22 | qthread_spawn( 23 | null_task, NULL, 0, NULL, 0, NULL, NO_SHEPHERD, QTHREAD_SPAWN_SIMPLE); 24 | } 25 | do { 26 | aligned_t tmp = donecount; 27 | qthread_yield(); 28 | if (tmp != donecount) { 29 | iprintf("donecount = %u\n", (unsigned int)donecount); 30 | } 31 | } while (donecount != count); 32 | 33 | return 0; 34 | } 35 | 36 | /* vim:set expandtab */ 37 | -------------------------------------------------------------------------------- /test/utils/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | # 3 | # Copyright (c) 2008 Sandia Corporation 4 | # 5 | 6 | SUBDIRS = rng 7 | -------------------------------------------------------------------------------- /test/utils/rng/.clang-format: -------------------------------------------------------------------------------- 1 | DisableFormat: true 2 | SortIncludes: Never 3 | -------------------------------------------------------------------------------- /test/utils/rng/.gitignore: -------------------------------------------------------------------------------- 1 | librng.la 2 | -------------------------------------------------------------------------------- /test/utils/rng/AUTHORS: -------------------------------------------------------------------------------- 1 | The Unbalanced Tree Search (UTS) Project Team: 2 | --------------------------------------------- 3 | 4 | University of Maryland: 5 | Bill Pugh 7 | 8 | The Ohio State University: 9 | James Dinan 12 | 13 | University of North Carolina, Chapel Hill: 14 | Stephen Olivier 18 | 19 | Supercomputing Research Center: 20 | Daniel Pryor 21 | 22 | * - indicates project PI 23 | -------------------------------------------------------------------------------- /test/utils/rng/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(qthreads_test_rng SHARED brg_sha1.c rng_brg.c) 2 | -------------------------------------------------------------------------------- /test/utils/rng/LICENSE: -------------------------------------------------------------------------------- 1 | The following license applies to the files in this directory ONLY: 2 | 3 | Copyright (c) 2009 See AUTHORS file for copyright holders 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, 9 | copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice shall be 15 | included in all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /test/utils/rng/Makefile.am: -------------------------------------------------------------------------------- 1 | # -*- Makefile -*- 2 | # 3 | # Copyright (c) 2008 Sandia Corporation 4 | # 5 | 6 | EXTRA_LTLIBRARIES = librng.la 7 | librng_la_SOURCES = \ 8 | brg_sha1.c \ 9 | brg_endian.h \ 10 | brg_sha1.h \ 11 | brg_types.h \ 12 | rng_brg.c \ 13 | rng_brg.h \ 14 | rng.h 15 | 16 | CLEANFILES = $(EXTRA_LTLIBRARIES) 17 | -------------------------------------------------------------------------------- /test/utils/rng/rng.h: -------------------------------------------------------------------------------- 1 | #ifndef _RNG_H 2 | #define _RNG_H 3 | 4 | /*********************************************************** 5 | * * 6 | * splitable random number generator to use: * 7 | * (default) sha1 hash * 8 | * (UTS_ALFG) additive lagged fibonacci generator * 9 | * * 10 | ***********************************************************/ 11 | 12 | #if defined(UTS_ALFG) 13 | # include "alfg.h" 14 | # define RNG_TYPE 1 15 | #elif defined(BRG_RNG) 16 | # include "rng_brg.h" 17 | # define RNG_TYPE 0 18 | #elif defined(DEVINE_RNG) 19 | # include "devine_sha1.h" 20 | # define RNG_TYPE 0 21 | #else 22 | # error "No random number generator selected." 23 | #endif 24 | 25 | #endif /* _RNG_H */ 26 | -------------------------------------------------------------------------------- /test/utils/rng/rng_brg.h: -------------------------------------------------------------------------------- 1 | #ifndef QT_RNG_BRG_H 2 | #define QT_RNG_BRG_H 3 | 4 | #include "brg_sha1.h" 5 | 6 | #define POS_MASK 0x7fffffff 7 | #define HIGH_BITS 0x80000000 8 | 9 | /**********************************/ 10 | /* random number generator state */ 11 | /**********************************/ 12 | struct state_t { 13 | uint8_t state[20]; 14 | }; 15 | 16 | typedef uint8_t RNG_state; 17 | 18 | /***************************************/ 19 | /* random number generator operations */ 20 | /***************************************/ 21 | void rng_init(RNG_state *state, int seed); 22 | void rng_spawn(RNG_state *mystate, RNG_state *newstate, int spawnNumber); 23 | int rng_rand(RNG_state *mystate); 24 | int rng_nextrand(RNG_state *mystate); 25 | char * rng_showstate(RNG_state *state, char *s); 26 | int rng_showtype(char *strBuf, int ind); 27 | 28 | #endif /* QT_RNG_BRG_H */ 29 | -------------------------------------------------------------------------------- /userguide/examples/barrier.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int const n = 30; 6 | qt_barrier_t *wait_on_me; 7 | aligned_t master = 0; 8 | 9 | static aligned_t incr(void *arg) { 10 | qthread_incr(&master, 1); 11 | qt_barrier_enter_id(wait_on_me, 0); 12 | return 0; 13 | } 14 | 15 | int main() { 16 | qthread_initialize(); 17 | size_t i; 18 | wait_on_me = qt_barrier_create(n + 1, REGION_BARRIER); 19 | for (i = 0; i < n; i++) qthread_fork(incr, NULL, NULL); 20 | qt_barrier_enter(wait_on_me); 21 | qt_barrier_destroy(wait_on_me); 22 | printf("Incremented %d times\n", (int)master); 23 | return 0; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /userguide/examples/fib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static aligned_t fib(void *arg) { 6 | aligned_t x = 0, y = 0; 7 | unsigned long n = (unsigned long)(uintptr_t)arg; 8 | 9 | if (n < 2) return n; 10 | 11 | qthread_fork(fib, (void *)n - 1, &x); 12 | qthread_fork(fib, (void *)n - 2, &y); 13 | 14 | qthread_readFF(NULL, &x); 15 | qthread_readFF(NULL, &y); 16 | 17 | return (x + y); 18 | } 19 | 20 | int main(int argc, char *argv[]) { 21 | aligned_t return_value = 0; 22 | unsigned long n = 0; 23 | 24 | if (argc > 1) n = atol(argv[1]); 25 | 26 | qthread_initialize(); 27 | 28 | qthread_fork(fib, (void *)n, &return_value); 29 | 30 | qthread_readFF(NULL, &return_value); 31 | 32 | printf("fib(%ld) = %ld\n", n, return_value); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /userguide/examples/fib_fast.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define THRESHOLD 20 6 | 7 | unsigned long fib_serial(unsigned long n) { 8 | int x, y; 9 | 10 | if (n < 2) return n; 11 | 12 | x = fib_serial(n - 1); 13 | y = fib_serial(n - 2); 14 | 15 | return (x + y); 16 | } 17 | 18 | static aligned_t fib(void *arg) { 19 | aligned_t x = 0, y = 0; 20 | unsigned long n = (unsigned long)(uintptr_t)arg; 21 | 22 | if (n < THRESHOLD) return (aligned_t)fib_serial(n); 23 | 24 | qthread_fork(fib, (void *)n - 1, &x); 25 | qthread_fork(fib, (void *)n - 2, &y); 26 | 27 | qthread_readFF(NULL, &x); 28 | qthread_readFF(NULL, &y); 29 | 30 | return (x + y); 31 | } 32 | 33 | int main(int argc, char *argv[]) { 34 | aligned_t return_value = 0; 35 | unsigned long n = 0; 36 | 37 | if (argc > 1) n = atol(argv[1]); 38 | 39 | qthread_initialize(); 40 | 41 | qthread_fork(fib, (void *)n, &return_value); 42 | 43 | qthread_readFF(NULL, &return_value); 44 | 45 | printf("fib(%ld) = %ld\n", n, return_value); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /userguide/examples/hello_world.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static aligned_t greeter(void *arg) { 5 | printf("Hello, world!\n"); 6 | 7 | return 0; 8 | } 9 | 10 | int main(int argc, char *argv[]) { 11 | aligned_t return_value = 0; 12 | 13 | qthread_initialize(); 14 | qthread_fork(greeter, NULL, &return_value); 15 | qthread_readFF(NULL, &return_value); 16 | 17 | return return_value; 18 | } 19 | -------------------------------------------------------------------------------- /userguide/examples/hello_world_loop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static void greeter(size_t const startat, size_t const stopat, void *arg) { 6 | size_t i; 7 | 8 | for (i = startat; i < stopat; i++) printf("#%lu: Hello, world!\n", i); 9 | } 10 | 11 | int main(int argc, char *argv[]) { 12 | qthread_initialize(); 13 | 14 | qt_loop(0, 10, greeter, NULL); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /userguide/examples/hello_world_loop_optimized.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static void greeter(size_t const startat, size_t const stopat, void *arg) { 6 | size_t i; 7 | 8 | for (i = startat; i < stopat; i++) printf("#%lu: Hello, world!\n", i); 9 | } 10 | 11 | int main(int argc, char *argv[]) { 12 | qthread_initialize(); 13 | 14 | qt_loop_balance(0, 10, greeter, NULL); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /userguide/examples/hello_world_multiple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static aligned_t greeter(void *arg) { 5 | printf("#%lu: Hello, world!\n", (unsigned long)(uintptr_t)arg); 6 | 7 | return 0; 8 | } 9 | 10 | int main(int argc, char *argv[]) { 11 | aligned_t return_value[10] = {0}; 12 | unsigned long i; 13 | 14 | qthread_initialize(); 15 | 16 | for (i = 0; i < 10; i++) qthread_fork(greeter, (void *)i, &return_value[i]); 17 | 18 | for (i = 0; i < 10; i++) qthread_readFF(NULL, &return_value[i]); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /userguide/examples/hello_world_safe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static aligned_t greeter(void *arg) { 8 | printf("Hello World!\n"); 9 | 10 | return 0; 11 | } 12 | 13 | int main(int argc, char *argv[]) { 14 | aligned_t return_value = 0; 15 | int status; 16 | 17 | status = qthread_initialize(); 18 | assert(status == QTHREAD_SUCCESS); 19 | 20 | status = qthread_fork(greeter, NULL, &return_value); 21 | assert(status == QTHREAD_SUCCESS); 22 | 23 | status = qthread_readFF(NULL, &return_value); 24 | assert(return_value == QTHREAD_SUCCESS); 25 | 26 | printf("greeter returned %lu\n", (unsigned long)return_value); 27 | 28 | return EXIT_SUCCESS; 29 | } 30 | -------------------------------------------------------------------------------- /userguide/examples/incr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int const n = 30; 5 | aligned_t master = 0; 6 | 7 | static aligned_t incr(void *arg) { 8 | qthread_incr(&master, 1); 9 | return 0; 10 | } 11 | 12 | int main() { 13 | qthread_initialize(); 14 | aligned_t rets[n]; 15 | size_t i; 16 | for (i = 0; i < n; i++) qthread_fork(incr, NULL, rets + i); 17 | 18 | for (i = 0; i < n; i++) qthread_readFF(NULL, rets + i); 19 | 20 | printf("Incremented %d times\n", (int)master); 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /userguide/examples/loopaccum_balance.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static void qtds_acc(void *a, void const *b) { *(double *)a += *(double *)b; } 6 | 7 | static void 8 | qtds_worker(size_t const startat, size_t const stopat, void *array, void *ret) { 9 | size_t i; 10 | double sum = 0; 11 | for (i = startat; i < stopat; i++) { sum += ((double *)array)[i]; } 12 | *(double *)ret = sum; 13 | } 14 | 15 | double qt_double_sum_example(double *array, size_t length) { 16 | double ret; 17 | qt_loopaccum_balance( 18 | 0, length, sizeof(double), &ret, qtds_worker, array, qtds_acc); 19 | return ret; 20 | } 21 | 22 | int main() { 23 | qthread_initialize(); 24 | double array[100]; 25 | size_t i; 26 | for (i = 0; i < 100; i++) { array[i] = rand(); } 27 | double ret = qt_double_sum_example(array, 100); 28 | printf("Sum = %f\n", ret); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /userguide/examples/numworksheps.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[]) { 6 | qthread_initialize(); 7 | 8 | printf("Number of workers: %d\n", qthread_num_workers()); 9 | printf("Number of shepherds: %d\n", qthread_num_shepherds()); 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /userguide/examples/sinc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int const n = 30; 9 | int const d = 4; 10 | 11 | typedef struct v_args_s { 12 | size_t depth; 13 | qt_sinc_t *sinc; 14 | } v_args_t; 15 | 16 | static void incr(void *target, void const *src) { 17 | *(int *)target += *(int *)src; 18 | } 19 | 20 | static aligned_t buildAndReduce(void *arg_) { 21 | size_t i; 22 | v_args_t *arg = (v_args_t *)arg_; 23 | qt_sinc_t sinc; 24 | aligned_t result, initial = 0; 25 | qt_sinc_init(&sinc, sizeof(aligned_t), &initial, incr, n); 26 | if (arg->depth > 1) { 27 | v_args_t args = {arg->depth - 1, &sinc}; 28 | for (i = 0; i < n; i++) qthread_fork(buildAndReduce, &args, NULL); 29 | qt_sinc_wait(&sinc, &result); 30 | qt_sinc_submit(arg->sinc, &result); 31 | } else { 32 | result = 1; 33 | qt_sinc_submit(arg->sinc, &result); 34 | } 35 | return 0; 36 | } 37 | 38 | int main() { 39 | aligned_t result, initial = 0; 40 | qthread_initialize(); 41 | qt_sinc_t sinc; 42 | qt_sinc_init(&sinc, sizeof(aligned_t), &initial, incr, n); 43 | v_args_t arg = {d, &sinc}; 44 | size_t i; 45 | for (i = 0; i < n; i++) qthread_fork(buildAndReduce, &arg, NULL); 46 | qt_sinc_wait(&sinc, &result); 47 | printf("Incremented %d times\n", (int)result); 48 | return 0; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /userguide/examples/worker_id.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct Vector { 6 | int n; 7 | int *array; 8 | } Vector; 9 | 10 | static aligned_t sum(void *arg) { 11 | int i; 12 | int *array = ((Vector *)arg)->array; 13 | int n = ((Vector *)arg)->n; 14 | int result = 0; 15 | qthread_worker_id_t id = qthread_worker(NULL); 16 | 17 | for (i = 0; i < n; i++) result += array[id * n + i]; 18 | 19 | return result; 20 | } 21 | 22 | int main(int argc, char *argv[]) { 23 | srand(1); 24 | int elems_per_worker = 100; 25 | qthread_initialize(); 26 | int n = qthread_num_workers(); 27 | int *array = malloc(n * elems_per_worker * sizeof(int)); 28 | aligned_t *return_value = malloc(n * elems_per_worker * sizeof(int)); 29 | int i, results = 0; 30 | 31 | printf("Number of workers: %d\n", n); 32 | printf("Number of array elements: %d\n", n * elems_per_worker); 33 | 34 | Vector input; 35 | input.n = n; 36 | input.array = array; 37 | 38 | for (i = 0; i < n * elems_per_worker; i++) array[i] = rand(); 39 | 40 | for (i = 0; i < n; i++) qthread_fork(sum, &input, return_value + i); 41 | 42 | for (i = 0; i < n; i++) { 43 | qthread_readFF(NULL, return_value + i); 44 | results += return_value[i]; 45 | } 46 | 47 | printf("Result: %d\n", results); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /userguide/images/fib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/fib.png -------------------------------------------------------------------------------- /userguide/images/fib_fast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/fib_fast.png -------------------------------------------------------------------------------- /userguide/images/fib_preconditioned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/fib_preconditioned.png -------------------------------------------------------------------------------- /userguide/images/hello_world.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/hello_world.png -------------------------------------------------------------------------------- /userguide/images/hello_world_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/hello_world_loop.png -------------------------------------------------------------------------------- /userguide/images/hello_world_multiple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/hello_world_multiple.png -------------------------------------------------------------------------------- /userguide/images/hello_world_optimized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/hello_world_optimized.png -------------------------------------------------------------------------------- /userguide/images/hello_world_safe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandialabs/qthreads/af9195e487bfecd9ce402d175a64692f2224d5ca/userguide/images/hello_world_safe.png --------------------------------------------------------------------------------