Yielding C Fun
==============
Introduction
------------
Yielding C Fun (YCF) is a tool that transforms functions written in a
subset of the C programming language so that they become yieldable. A
yieldable function can be suspended/yielded/paused/trapped (either
automatically or where the user has inserted a particular statement)
and then be resumed at a later point. Yileldable functions are also
called [coroutines](https://en.wikipedia.org/wiki/Coroutine).
Difference Between Yielding C Fun and Coroutine Libraries
---------------------------------------------------------
Several libraries implement [coroutine support for the C programming
language](https://en.wikipedia.org/wiki/Coroutine#Implementations_for_C)
(e.g., \[[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11],
[12], [13]\]). These libraries either rely on platform-specific code
or do not save call stack variables. Yielding C Fun (YCF) does not
have any of these two limitations. YCF can accomplish this as it is a
source-to-source transformation tool and not only a library.
YCF has been created to make it easier to implement yielding Erlang
[NIFs](http://erlang.org/doc/tutorial/nif.html) and
[BIFs](http://erlang.org/pipermail/erlang-questions/2009-October/046899.html)
(i.e., Erlang functions that are written in C). Below are examples of
YCF features that are useful when implementing yielding Erlang NIFs
and BIFs:
* YCF automatically generates a destroy function for each yieldable
function. The destroy function frees resources that are used by a
suspended function. The destroy function is useful when a suspended
function needs to abort (e.g., when the Erlang process that invoked
the function has died).
* YCF can automatically insert code that yields functions after a
user specifiable number of loop iterations and goto statements.
* YCF has a hook system that lets the user insert code that is
triggered when certain events happen (e.g., when a function
yields).
The main limitations of YCF are that it cannot handle all valid C code
and that it cannot make library functions without source code
yieldable. Pointers to stack-allocated data are also not allowed (YCF
has a memory allocation function called `YCF_STACK_ALLOC` to work
around this issue).
Requirements
------------
* A C99 compatible C compiler
* make (optional but useful for building)
Compile and Test
----------------
Build the executable `$YCF_ROOT/bin/yielding_c_fun.bin`:
make
Build the executable and run all tests:
make test
Getting Started
---------------
A brief introduction tutorial can be found
[here](doc/thread_tutorial.md). This tutorial is a perfect place to
start!
The "[test/examples/](test/examples/)" folder in this repository
contains many small examples that are useful when learning about
YCF. YCF's automatic tests use these examples as well. The driver for
these tests is located in `test/test.sh`.
[This Erlang NIF example](test/examples/sha256_erlang_nif/) shows how
one can use YCF to write a yielding Erlang NIF library.
Command Line Parameters
-----------------------
```
Usage: yielding_c_fun [-h]
yielding_c_fun [-use_gc [-print_gc_info]]
[-log_max_mem_usage log_file]
[(( -f | -frec | -fnoauto ) function_name)...
[-output_file_name output_file]
[-header_file_name header_file]
[-debug]
[-only_yielding_funs]
[-static_aux_funs]
input_c_file]]
```
* `-h`
Print help text
* `-use_gc`
Use garbage collection. The garbage collection system assumes that
the C call stack consists of a continuous memory block and is
therefore not enabled by default even though this assumption is
valid on all major platforms. YCF does not reclaim any allocated
memory if the `-use_gc` flag is not set.
* `-print_gc_info`
(For debugging) Print garbage collection information to `stderr`
* `-log_max_mem_usage log_file`
(For debugging) Print the peak memory usage of the tool to the file
`log_file`
* `-fnoauto function_name`
Generate a yieldable version of the function named
function_name. The user can use `YCF_YIELD()`,
`YCF_YIELD_NO_REDS()`, and `YCF_CONSUME_REDS(N)` to control
when and where the function should yield. See the section titled
"Special Statements and Macros" for more information.
* `-f function_name`
Generate a yieldable version of the function named
`function_name`. The generated function automatically decrements the
reduction counter by one at the beginning of loop bodies and before
goto statements. The function yields automatically if the reduction
counter reaches a value that is zero or smaller after it has been
decremented.
* `-frec function_name`
Same as the `-f` option with the exception that the generated function
also decrements one reduction before calls to other yieldable
functions and before returning. The function yields automatically if
the reduction counter reaches a value that is zero or smaller after
it has been decremented.
* `-fexternal function_name`
YCF expects that a yielding version of the function called
`function_name` is generated externally. Calls to the function
called `function_name` from yielding functions calls the externally
generated yielding version of the function called `function_name`.
* `-output_file_name output_file`
Output the generated code to a file named output_file. The output
is printed to standard output if this parameter is unspecified.
* `-header_file_name header_file`
Generate a header file containing only declarations for the generated
functions and write the header file to the file named header_file.
* `-debug`
Generate debug code that executes when a function yields. The debug
code searches the call stack of the yielding functions for pointers
to data that is allocated on the call stack. The program crashes
with an error message if any such pointer is found.
The generated debug code depends on that a function called
`ycf_debug_get_stack_start()` is declared somewhere in the
program. The `ycf_debug_get_stack_start()` functions should return a
value of type `void*`. Example:
static _Thread_local void* ycf_debug_global_stack_start_ptr = NULL;
void* ycf_debug_get_stack_start() {
return ycf_debug_global_stack_start_ptr;
}
If `ycf_debug_get_stack_start()` returns `NULL`, the value of the
`ycf_yield_state` parameter will be used as the start of the stack (it
is assumed that the stack grows towards lower addresses). If
`ycf_debug_get_stack_start()` returns something different than `NULL`,
that value will be used as the start of the stack. To check that
nested yielding functions do not have pointers to the call stack,
one have to make sure that `ycf_debug_get_stack_start()` returns
something different than `NULL` (otherwise, each function will just
check for pointers to its own frame). Example:
ycf_debug_global_stack_start_ptr = &wb;
ret = fun_ycf_gen_yielding(&nr_of_reductions,&wb,NULL,allocator,freer,NULL,0,NULL,1);
ycf_debug_global_stack_start_ptr = NULL;
* `-only_yielding_funs`
Print only the generated functions and struct declarations. The
default behavior is to insert the generated functions into a copy of
the input source file.
* `-static_aux_funs`
Make the generated auxiliary functions static (i.e., local to the C
compilation unit)
* `input_c_file`
The source file containing the functions that YCF shall create
yieldable versions of. YCF does not do any macro expansions. There
are several restrictions on the code that YCF can handle that are
described in the "Code Restrictions" section below.
Generated Functions
-------------------
YCF generates three functions for each function name that it is
given. These functions have
没有合适的资源?快使用搜索试试~ 我知道了~
erlang_版本24.3.4.4
需积分: 25 5 下载量 168 浏览量
2022-09-03
09:58:26
上传
评论
收藏 102.8MB GZ 举报
温馨提示
共14791个文件
erl:3908个
xml:2346个
beam:1436个
erlang 安装包
资源详情
资源评论
资源推荐
收起资源包目录
erlang_版本24.3.4.4 (14791个子文件)
suppress.patched.3.6.0 6KB
x.erl.1 70B
kurt2.LOG.1 53B
kurt.LOG.1 53B
zzz.terms.1197 818B
1k_file 1000B
1M_file 977KB
x.erl.2 72B
kurt2.LOG.2 53B
kurt.LOG.2 53B
zzz.terms.2224 126B
zzz.terms.24619 560B
zzz.terms.25681 132B
zzz.terms.26563 559B
zzz.terms.26744 3KB
zzz.terms.27459 2KB
tags.3 2KB
kurt.LOG.3 53B
kurt2.LOG.3 53B
Dockerfile.32-bit 819B
kurt2.LOG.4 53B
kurt.LOG.4 53B
zzz.terms.527 1KB
Dockerfile.64-bit 1009B
zzz.terms.8929 2KB
abs 457B
abs 353B
add_abstract_code 1KB
andalso_test 0B
wx.app 5KB
snmp.app 4KB
kernel.app 4KB
inets.app 3KB
megaco.app 3KB
ssl.app 3KB
stdlib.app 2KB
diameter.app 2KB
common_test.app 2KB
compiler.app 2KB
observer.app 2KB
dialyzer.app 2KB
ssh.app 2KB
debugger.app 1KB
sasl.app 1KB
tools.app 1KB
os_mon.app 1KB
runtime_tools.app 1KB
mnesia.app 1KB
reltool.app 1KB
et.app 1KB
crypto.app 978B
erl_interface.app 898B
app1.app 877B
xmerl.app 781B
edoc.app 714B
public_key.app 506B
eunit.app 494B
topApp3.app 493B
tftp.app 469B
syntax_tools.app 454B
topApp2.app 422B
ftp.app 421B
parsetools.app 404B
appinc.app 398B
erl_docgen.app 397B
topApp.app 396B
appinc2top.app 375B
primary_archive_dummy.app 340B
odbc.app 338B
appinc2.app 325B
primary_archive_dict.app 319B
archive_script_dict.app 313B
asn1.app 312B
z.app 307B
app_faulty.app 306B
appinc1.app 304B
appinc1x.app 301B
code_archive_dict.app 301B
archive_script_dummy.app 299B
appinc2A.app 297B
dummy.app 290B
u.app 284B
u.app 284B
appinc2B.app 279B
eldap.app 269B
myApp.app 263B
app1.app 261B
app1.app 261B
app1.app 261B
app1.app 261B
y.app 256B
c.app 254B
app2.app 251B
app2.app 251B
a.app 244B
a.app 244B
a.app 244B
a.app 244B
a.app 244B
many_mods.app 228B
共 14791 条
- 1
- 2
- 3
- 4
- 5
- 6
- 148
黑心的绿萝
- 粉丝: 447
- 资源: 3
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0