Compare commits
10 Commits
962bcbd917
...
fdebbb224e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fdebbb224e | ||
![]() |
ae3749aa31 | ||
![]() |
08e6338d23 | ||
![]() |
0756884d41 | ||
![]() |
7100af72ca | ||
![]() |
5dbad67352 | ||
![]() |
f045b33647 | ||
![]() |
af8a2d7215 | ||
![]() |
6f8e168ae3 | ||
![]() |
cf112a57fa |
56
Makefile
56
Makefile
@ -614,21 +614,30 @@ iob_addfile.o: io/iob_addfile.c iob_internal.h iob.h libowfat/io.h \
|
||||
iob_addfile_close.o: io/iob_addfile_close.c iob_internal.h iob.h \
|
||||
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
|
||||
libowfat/uint32.h libowfat/compiler.h libowfat/array.h array.h
|
||||
iob_adds.o: io/iob_adds.c str.h libowfat/compiler.h iob.h libowfat/io.h \
|
||||
iob_adds.o: io/iob_adds.c iob_internal.h iob.h libowfat/io.h \
|
||||
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
|
||||
libowfat/array.h
|
||||
iob_adds_free.o: io/iob_adds_free.c str.h libowfat/compiler.h iob.h \
|
||||
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
|
||||
libowfat/uint32.h libowfat/array.h
|
||||
iob_bytesleft.o: io/iob_bytesleft.c iob.h libowfat/io.h libowfat/uint64.h \
|
||||
libowfat/taia.h libowfat/tai.h libowfat/uint32.h libowfat/compiler.h \
|
||||
libowfat/array.h
|
||||
libowfat/compiler.h libowfat/array.h array.h
|
||||
iob_adds_free.o: io/iob_adds_free.c iob_internal.h iob.h libowfat/io.h \
|
||||
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
|
||||
libowfat/compiler.h libowfat/array.h array.h
|
||||
iob_bytesleft.o: io/iob_bytesleft.c iob_internal.h iob.h libowfat/io.h \
|
||||
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
|
||||
libowfat/compiler.h libowfat/array.h array.h
|
||||
iob_free.o: io/iob_free.c iob_internal.h iob.h libowfat/io.h \
|
||||
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
|
||||
libowfat/compiler.h libowfat/array.h array.h
|
||||
iob_init.o: io/iob_init.c byte.h libowfat/compiler.h iob_internal.h iob.h \
|
||||
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
|
||||
libowfat/uint32.h libowfat/array.h array.h
|
||||
iob_init_autofree.o: io/iob_init_autofree.c iob_internal.h iob.h \
|
||||
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
|
||||
libowfat/uint32.h libowfat/compiler.h libowfat/array.h array.h
|
||||
iob_new.o: io/iob_new.c byte.h libowfat/compiler.h iob_internal.h iob.h \
|
||||
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
|
||||
libowfat/uint32.h libowfat/array.h array.h
|
||||
iob_new_autofree.o: io/iob_new_autofree.c iob_internal.h iob.h \
|
||||
libowfat/io.h libowfat/uint64.h libowfat/taia.h libowfat/tai.h \
|
||||
libowfat/uint32.h libowfat/compiler.h libowfat/array.h array.h
|
||||
iob_prefetch.o: io/iob_prefetch.c iob_internal.h iob.h libowfat/io.h \
|
||||
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
|
||||
libowfat/compiler.h libowfat/array.h array.h
|
||||
@ -655,6 +664,10 @@ iom_init.o: io/iom_init.c io_internal.h libowfat/io.h libowfat/uint64.h \
|
||||
libowfat/taia.h libowfat/tai.h libowfat/uint32.h libowfat/compiler.h \
|
||||
libowfat/array.h libowfat/iarray.h haveepoll.h havekqueue.h \
|
||||
havedevpoll.h havesigio.h
|
||||
iom_requeue.o: io/iom_requeue.c io_internal.h libowfat/io.h \
|
||||
libowfat/uint64.h libowfat/taia.h libowfat/tai.h libowfat/uint32.h \
|
||||
libowfat/compiler.h libowfat/array.h libowfat/iarray.h haveepoll.h \
|
||||
havekqueue.h havedevpoll.h havesigio.h
|
||||
iom_wait.o: io/iom_wait.c io_internal.h libowfat/io.h libowfat/uint64.h \
|
||||
libowfat/taia.h libowfat/tai.h libowfat/uint32.h libowfat/compiler.h \
|
||||
libowfat/array.h libowfat/iarray.h haveepoll.h havekqueue.h \
|
||||
@ -883,7 +896,8 @@ socket_tcp4.o: socket/socket_tcp4.c socket.h libowfat/compiler.h \
|
||||
socket_tcp4b.o: socket/socket_tcp4b.c windoze.h socket.h \
|
||||
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h
|
||||
socket_tcp6.o: socket/socket_tcp6.c haveip6.h socket.h \
|
||||
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h
|
||||
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h \
|
||||
windoze.h
|
||||
socket_tcp6b.o: socket/socket_tcp6b.c windoze.h haveip6.h socket.h \
|
||||
libowfat/compiler.h libowfat/uint16.h libowfat/uint32.h ndelay.h
|
||||
socket_tryreservein.o: socket/socket_tryreservein.c windoze.h socket.h \
|
||||
@ -1063,25 +1077,25 @@ t.o: t.c fmt.h libowfat/byte.h libowfat/compiler.h scan.h str.h uint16.h \
|
||||
parse.h libowfat/buffer.h CAS.h io_internal.h libowfat/io.h \
|
||||
libowfat/array.h libowfat/iarray.h haveepoll.h havekqueue.h \
|
||||
havedevpoll.h havesigio.h
|
||||
BYTE_OBJS=byte_chr.o byte_copy.o byte_copyr.o byte_diff.o byte_equal_notimingattack.o byte_rchr.o byte_zero.o
|
||||
FMT_OBJS=fmt_8long.o fmt_8longlong.o fmt_asn1derlength.o fmt_asn1dertag.o fmt_double.o fmt_escapecharc.o fmt_escapecharhtml.o fmt_escapecharjson.o fmt_escapecharquotedprintable.o fmt_escapecharquotedprintableutf8.o fmt_escapecharxml.o fmt_fill.o fmt_httpdate.o fmt_human.o fmt_humank.o fmt_iso8601.o fmt_long.o fmt_longlong.o fmt_minus.o fmt_netstring.o fmt_pad.o fmt_pb_double.o fmt_pb_float.o fmt_pb_int.o fmt_pb_sint.o fmt_pb_string.o fmt_pb_tag.o fmt_pb_type0_sint.o fmt_pb_type1_double.o fmt_pb_type1_fixed64.o fmt_pb_type2_string.o fmt_pb_type5_fixed32.o fmt_pb_type5_float.o fmt_plusminus.o fmt_str.o fmt_strm_internal.o fmt_strn.o fmt_tohex.o fmt_ulong.o fmt_ulong0.o fmt_ulonglong.o fmt_utf8.o fmt_varint.o fmt_xlong.o fmt_xlonglong.o fmt_xmlescape.o
|
||||
BYTE_OBJS=byte_chr.o byte_copy.o byte_copyr.o byte_diff.o byte_equal_notimingattack.o byte_rchr.o byte_start.o byte_starts.o byte_zero.o
|
||||
FMT_OBJS=fmt_8long.o fmt_8longlong.o fmt_asn1derlength.o fmt_asn1dertag.o fmt_double.o fmt_escapecharc.o fmt_escapecharhtml.o fmt_escapecharjson.o fmt_escapecharquotedprintable.o fmt_escapecharquotedprintableutf8.o fmt_escapecharxml.o fmt_fill.o fmt_httpdate.o fmt_human.o fmt_humank.o fmt_iso8601.o fmt_long.o fmt_longlong.o fmt_minus.o fmt_netstring.o fmt_pad.o fmt_pb_double.o fmt_pb_float.o fmt_pb_int.o fmt_pb_sint.o fmt_pb_string.o fmt_pb_tag.o fmt_pb_type0_sint.o fmt_pb_type1_double.o fmt_pb_type1_fixed64.o fmt_pb_type2_string.o fmt_pb_type5_fixed32.o fmt_pb_type5_float.o fmt_plusminus.o fmt_str.o fmt_strm_internal.o fmt_strn.o fmt_tohex.o fmt_ulong0.o fmt_ulong.o fmt_ulonglong.o fmt_utf8.o fmt_varint.o fmt_xlong.o fmt_xlonglong.o fmt_xmlescape.o
|
||||
SCAN_OBJS=scan_8int.o scan_8long.o scan_8longlong.o scan_8longn.o scan_8short.o scan_asn1derlength.o scan_asn1dertag.o scan_charsetnskip.o scan_double.o scan_fromhex.o scan_httpdate.o scan_int.o scan_iso8601.o scan_long.o scan_longlong.o scan_longn.o scan_netstring.o scan_noncharsetnskip.o scan_nonwhitenskip.o scan_pb_tag.o scan_pb_type0_sint.o scan_pb_type1_double.o scan_pb_type1_fixed64.o scan_pb_type2_stringlen.o scan_pb_type5_fixed32.o scan_pb_type5_float.o scan_plusminus.o scan_short.o scan_uint.o scan_ulong.o scan_ulonglong.o scan_ulongn.o scan_ushort.o scan_utf8.o scan_utf8_sem.o scan_varint.o scan_whitenskip.o scan_xint.o scan_xlong.o scan_xlonglong.o scan_xlongn.o scan_xshort.o
|
||||
STR_OBJS=str_chr.o str_copy.o str_diff.o str_diffn.o str_len.o str_rchr.o str_start.o
|
||||
UINT_OBJS=uint16_pack.o uint16_pack_big.o uint16_read.o uint16_read_big.o uint16_unpack.o uint16_unpack_big.o uint32_pack.o uint32_pack_big.o uint32_read.o uint32_read_big.o uint32_unpack.o uint32_unpack_big.o uint64_pack.o uint64_pack_big.o uint64_read.o uint64_read_big.o uint64_unpack.o uint64_unpack_big.o
|
||||
OPEN_OBJS=open_append.o open_excl.o open_read.o open_rw.o open_trunc.o open_write.o openreadclose.o readclose.o
|
||||
STRALLOC_OBJS=stralloc_append.o stralloc_cat.o stralloc_catb.o stralloc_catlong0.o stralloc_catm_internal.o stralloc_cats.o stralloc_catulong0.o stralloc_chomp.o stralloc_chop.o stralloc_copy.o stralloc_copyb.o stralloc_copys.o stralloc_diff.o stralloc_diffs.o stralloc_free.o stralloc_init.o stralloc_ready.o stralloc_readyplus.o stralloc_starts.o stralloc_zero.o
|
||||
UINT_OBJS=uint16_pack_big.o uint16_pack.o uint16_read_big.o uint16_read.o uint16_unpack_big.o uint16_unpack.o uint32_pack_big.o uint32_pack.o uint32_read_big.o uint32_read.o uint32_unpack_big.o uint32_unpack.o uint64_pack_big.o uint64_pack.o uint64_read_big.o uint64_read.o uint64_unpack_big.o uint64_unpack.o
|
||||
OPEN_OBJS=open_append.o open_excl.o open_read.o openreadclose.o open_rw.o open_trunc.o open_write.o readclose.o
|
||||
STRALLOC_OBJS=stralloc_append.o stralloc_catb.o stralloc_cat.o stralloc_catlong0.o stralloc_catm_internal.o stralloc_cats.o stralloc_catulong0.o stralloc_chomp.o stralloc_chop.o stralloc_copyb.o stralloc_copy.o stralloc_copys.o stralloc_diff.o stralloc_diffs.o stralloc_free.o stralloc_init.o stralloc_ready.o stralloc_readyplus.o stralloc_starts.o stralloc_zero.o
|
||||
UNIX_OBJS=iopause.o ndelay_off.o ndelay_on.o winsock2errno.o
|
||||
SOCKET_OBJS=fmt_ip4.o fmt_ip6.o fmt_ip6_flat.o fmt_ip6c.o fmt_ip6if.o fmt_ip6ifc.o init.o scan_ip4.o scan_ip6.o scan_ip6_flat.o scan_ip6if.o socket_accept4.o socket_accept6.o socket_bind4.o socket_bind4_reuse.o socket_bind6.o socket_bind6_reuse.o socket_broadcast.o socket_connect4.o socket_connect6.o socket_connected.o socket_deferaccept.o socket_fastopen.o socket_fastopen_connect4.o socket_fastopen_connect6.o socket_getifidx.o socket_getifname.o socket_ip4loopback.o socket_listen.o socket_local4.o socket_local6.o socket_mchopcount6.o socket_mcjoin4.o socket_mcjoin6.o socket_mcleave4.o socket_mcleave6.o socket_mcloop4.o socket_mcloop6.o socket_mcttl4.o socket_noipv6.o socket_quickack.o socket_recv4.o socket_recv6.o socket_remote4.o socket_remote6.o socket_sctp4.o socket_sctp4b.o socket_sctp6.o socket_sctp6b.o socket_send4.o socket_send6.o socket_tcp4.o socket_tcp4b.o socket_tcp6.o socket_tcp6b.o socket_tryreservein.o socket_udp4.o socket_udp6.o socket_v4mappedprefix.o socket_v6any.o socket_v6loopback.o
|
||||
BUFFER_OBJS=buffer_0.o buffer_0small.o buffer_1.o buffer_1small.o buffer_2.o buffer_close.o buffer_feed.o buffer_flush.o buffer_free.o buffer_fromarray.o buffer_frombuf.o buffer_fromsa.o buffer_get.o buffer_get_new_token_sa.o buffer_get_new_token_sa_pred.o buffer_get_token.o buffer_get_token_pred.o buffer_get_token_sa.o buffer_get_token_sa_pred.o buffer_getc.o buffer_getline.o buffer_getline_sa.o buffer_getn.o buffer_getnewline_sa.o buffer_init.o buffer_init_free.o buffer_mmapread.o buffer_munmap.o buffer_peek.o buffer_put.o buffer_put8long.o buffer_putalign.o buffer_puterror.o buffer_puterror2.o buffer_putflush.o buffer_putlong.o buffer_putlonglong.o buffer_putm_internal.o buffer_putm_internal_flush.o buffer_putnlflush.o buffer_puts.o buffer_putsa.o buffer_putsaflush.o buffer_putsalign.o buffer_putsflush.o buffer_putspace.o buffer_putulong.o buffer_putulonglong.o buffer_putxlong.o buffer_seek.o buffer_stubborn.o buffer_stubborn2.o buffer_tosa.o errmsg_iam.o errmsg_info.o errmsg_infosys.o errmsg_puts.o errmsg_warn.o errmsg_warnsys.o errmsg_write.o
|
||||
MMAP_OBJS=mmap_private.o mmap_read.o mmap_readat.o mmap_shared.o mmap_unmap.o
|
||||
SOCKET_OBJS=fmt_ip4.o fmt_ip6.o fmt_ip6c.o fmt_ip6_flat.o fmt_ip6if.o fmt_ip6ifc.o init.o scan_ip4.o scan_ip6.o scan_ip6_flat.o scan_ip6if.o socket_accept4.o socket_accept4_flags.o socket_accept4_makenonblocking.o socket_accept4_makenonblocking_setcloseonexec.o socket_accept4_setcloseonexec.o socket_accept6.o socket_accept6_flags.o socket_accept6_makenonblocking.o socket_accept6_makenonblocking_setcloseonexec.o socket_accept6_setcloseonexec.o socket_bind4.o socket_bind4_reuse.o socket_bind6.o socket_bind6_reuse.o socket_broadcast.o socket_connect4.o socket_connect6.o socket_connected.o socket_deferaccept.o socket_fastopen.o socket_fastopen_connect4.o socket_fastopen_connect6.o socket_getifidx.o socket_getifname.o socket_ip4loopback.o socket_listen.o socket_local4.o socket_local6.o socket_mchopcount6.o socket_mcjoin4.o socket_mcjoin6.o socket_mcleave4.o socket_mcleave6.o socket_mcloop4.o socket_mcloop6.o socket_mcttl4.o socket_noipv6.o socket_quickack.o socket_recv4.o socket_recv6.o socket_remote4.o socket_remote6.o socket_sctp4b.o socket_sctp4.o socket_sctp6b.o socket_sctp6.o socket_send4.o socket_send6.o socket_tcp4b.o socket_tcp4.o socket_tcp6b.o socket_tcp6.o socket_tryreservein.o socket_udp4.o socket_udp6.o socket_v4mappedprefix.o socket_v6any.o socket_v6loopback.o
|
||||
BUFFER_OBJS=bs_capacityassert.o bs_capacitycheck.o bs_capacityleft.o bs_consumeleftovers.o bs_err.o bs_get.o bs_init_bstream_size.o bs_init_iobuf.o bs_init_iobuf_size.o bs_init_membuf.o bs_nomoredataassert.o bs_peek.o bs_seterrorstate.o bs_skip.o buffer_0.o buffer_0small.o buffer_1.o buffer_1small.o buffer_2.o buffer_close.o buffer_feed.o buffer_flush.o buffer_free.o buffer_fromarray.o buffer_frombuf.o buffer_fromsa.o buffer_get.o buffer_getc.o buffer_getline.o buffer_getline_sa.o buffer_getn.o buffer_getnewline_sa.o buffer_get_new_token_sa.o buffer_get_new_token_sa_pred.o buffer_get_token.o buffer_get_token_pred.o buffer_get_token_sa.o buffer_get_token_sa_pred.o buffer_init_allocbuf.o buffer_init.o buffer_init_free.o buffer_init_read_allocbuf.o buffer_init_read.o buffer_init_staticcontents.o buffer_init_staticcontents_free.o buffer_init_write_allocbuf.o buffer_init_write.o buffer_mmapread.o buffer_munmap.o buffer_peek.o buffer_peekc.o buffer_put8long.o buffer_putalign.o buffer_put.o buffer_puterror2.o buffer_puterror.o buffer_putflush.o buffer_putlong.o buffer_putlonglong.o buffer_putm_internal.o buffer_putm_internal_flush.o buffer_putnlflush.o buffer_putsa.o buffer_putsaflush.o buffer_putsalign.o buffer_puts.o buffer_putsflush.o buffer_putspace.o buffer_putulong.o buffer_putulonglong.o buffer_putxlong.o buffer_seek.o buffer_stubborn2.o buffer_stubborn.o buffer_tosa.o errmsg_iam.o errmsg_info.o errmsg_infosys.o errmsg_puts.o errmsg_warn.o errmsg_warnsys.o errmsg_write.o prs_asciiz.o prs_asciiz_fixedlen.o prs_readblob.o prs_u16_big.o prs_u16.o prs_u32_big.o prs_u32.o prs_u64_big.o prs_u64.o
|
||||
MMAP_OBJS=mmap_private.o mmap_readat.o mmap_read.o mmap_shared.o mmap_unmap.o
|
||||
TAIA_OBJS=taia_add.o taia_addsec.o taia_approx.o taia_frac.o taia_half.o taia_less.o taia_now.o taia_pack.o taia_sub.o taia_tai.o taia_uint.o taia_unpack.o
|
||||
TAI_OBJS=tai_add.o tai_now.o tai_pack.o tai_sub.o tai_uint.o tai_unpack.o
|
||||
DNS_OBJS=dns_dfd.o dns_domain.o dns_dtda.o dns_ip.o dns_ip6.o dns_ipq.o dns_ipq6.o dns_mx.o dns_name.o dns_nd.o dns_nd6.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o dns_resolve.o dns_sortip.o dns_sortip6.o dns_transmit.o dns_txt.o
|
||||
DNS_OBJS=dns_dfd.o dns_domain.o dns_dtda.o dns_ip6.o dns_ip.o dns_ipq6.o dns_ipq.o dns_mx.o dns_name.o dns_nd6.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o dns_rcrw.o dns_resolve.o dns_sortip6.o dns_sortip.o dns_transmit.o dns_txt.o
|
||||
CASE_OBJS=case_diffb.o case_diffs.o case_lowerb.o case_lowers.o case_starts.o
|
||||
MULT_OBJS=imult16.o imult32.o imult64.o range_arrayinbuf.o range_str2inbuf.o range_str4inbuf.o range_strinbuf.o umult16.o umult32.o umult64.o
|
||||
ARRAY_OBJS=array_allocate.o array_bytes.o array_cat.o array_cat0.o array_catb.o array_cate.o array_cats.o array_cats0.o array_equal.o array_fail.o array_get.o array_length.o array_reset.o array_start.o array_trunc.o array_truncate.o iarray_allocate.o iarray_free.o iarray_get.o iarray_init.o iarray_length.o
|
||||
IO_OBJS=io_appendfile.o io_block.o io_canread.o io_canwrite.o io_check.o io_close.o io_closeonexec.o io_createfile.o io_debugstring.o io_dontwantread.o io_dontwantwrite.o io_eagain.o io_eagain_read.o io_eagain_write.o io_fd.o io_finishandshutdown.o io_getcookie.o io_mmapwritefile.o io_nonblock.o io_passfd.o io_pipe.o io_readfile.o io_readwritefile.o io_receivefd.o io_sendfile.o io_setcookie.o io_sigpipe.o io_socketpair.o io_timedout.o io_timeout.o io_timeouted.o io_tryread.o io_tryreadtimeout.o io_trywrite.o io_trywritetimeout.o io_wait.o io_waitread.o io_waituntil.o io_waituntil2.o io_waitwrite.o io_wantread.o io_wantwrite.o iob_addbuf.o iob_addbuf_free.o iob_addbuf_internal.o iob_addbuf_munmap.o iob_addfile.o iob_addfile_close.o iob_adds.o iob_adds_free.o iob_bytesleft.o iob_free.o iob_new.o iob_prefetch.o iob_reset.o iob_send.o iob_write.o
|
||||
TEXTCODE_OBJS=base64.o base64url.o fmt_base64.o fmt_base64url.o fmt_cescape.o fmt_foldwhitespace.o fmt_hexdump.o fmt_html.o fmt_html_tagarg.o fmt_jsonescape.o fmt_ldapescape.o fmt_ldapescape2.o fmt_quotedprintable.o fmt_to_array.o fmt_to_sa.o fmt_tofrom_array.o fmt_urlencoded.o fmt_uuencoded.o fmt_xml.o fmt_yenc.o scan_base64.o scan_base64url.o scan_cescape.o scan_hexdump.o scan_html.o scan_jsonescape.o scan_ldapescape.o scan_quotedprintable.o scan_to_array.o scan_to_sa.o scan_tofrom_array.o scan_urlencoded.o scan_uuencoded.o scan_yenc.o
|
||||
ARRAY_OBJS=array_allocate.o array_bytes.o array_cat0.o array_catb.o array_cat.o array_cate.o array_cats0.o array_cats.o array_equal.o array_fail.o array_get.o array_length.o array_reset.o array_start.o array_truncate.o array_trunc.o iarray_allocate.o iarray_free.o iarray_get.o iarray_init.o iarray_length.o
|
||||
IO_OBJS=io_appendfile.o iob_addbuf.o iob_addbuf_free.o iob_addbuf_internal.o iob_addbuf_munmap.o iob_addfile.o iob_addfile_close.o iob_adds.o iob_adds_free.o iob_bytesleft.o iob_free.o iob_init_autofree.o iob_init.o io_block.o iob_new_autofree.o iob_new.o iob_prefetch.o iob_reset.o iob_send.o iob_write.o io_canread.o io_canwrite.o io_check.o io_close.o io_closeonexec.o io_createfile.o io_debugstring.o io_dontwantread.o io_dontwantwrite.o io_eagain.o io_eagain_read.o io_eagain_write.o io_fd.o io_finishandshutdown.o io_getcookie.o iom_abort.o iom_add.o iom_init.o io_mmapwritefile.o iom_requeue.o iom_wait.o io_nonblock.o io_passfd.o io_pipe.o io_readfile.o io_readwritefile.o io_receivefd.o io_sendfile.o io_setcookie.o io_sigpipe.o io_socketpair.o io_timedout.o io_timeout.o io_timeouted.o io_tryread.o io_tryreadtimeout.o io_trywrite.o io_trywritetimeout.o io_wait.o io_waitread.o io_waituntil2.o io_waituntil.o io_waitwrite.o io_wantread.o io_wantwrite.o
|
||||
TEXTCODE_OBJS=base64.o base64url.o fmt_base64.o fmt_base64url.o fmt_cescape.o fmt_foldwhitespace.o fmt_hexdump.o fmt_html.o fmt_html_tagarg.o fmt_jsonescape.o fmt_ldapescape2.o fmt_ldapescape.o fmt_quotedprintable.o fmt_to_array.o fmt_tofrom_array.o fmt_to_sa.o fmt_urlencoded.o fmt_uuencoded.o fmt_xml.o fmt_yenc.o scan_base64.o scan_base64url.o scan_cescape.o scan_hexdump.o scan_html.o scan_jsonescape.o scan_ldapescape.o scan_quotedprintable.o scan_to_array.o scan_tofrom_array.o scan_to_sa.o scan_urlencoded.o scan_uuencoded.o scan_yenc.o
|
||||
CDB_OBJS=cdb.o cdb_hash.o cdb_make.o cdb_traverse.o
|
||||
CRITBIT_OBJS=critbit.o
|
||||
|
||||
|
@ -478,7 +478,10 @@
|
||||
{ "directory": "@", "file": "io/iob_adds_free.c", "output": "iob_adds_free.o", "arguments": [ "clang", "-c", "io/iob_adds_free.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_bytesleft.c", "output": "iob_bytesleft.o", "arguments": [ "clang", "-c", "io/iob_bytesleft.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_free.c", "output": "iob_free.o", "arguments": [ "clang", "-c", "io/iob_free.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_init.c", "output": "iob_init.o", "arguments": [ "clang", "-c", "io/iob_init.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_init_autofree.c", "output": "iob_init_autofree.o", "arguments": [ "clang", "-c", "io/iob_init_autofree.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_new.c", "output": "iob_new.o", "arguments": [ "clang", "-c", "io/iob_new.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_new_autofree.c", "output": "iob_new_autofree.o", "arguments": [ "clang", "-c", "io/iob_new_autofree.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_prefetch.c", "output": "iob_prefetch.o", "arguments": [ "clang", "-c", "io/iob_prefetch.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_reset.c", "output": "iob_reset.o", "arguments": [ "clang", "-c", "io/iob_reset.c", "-I." ]},
|
||||
{ "directory": "@", "file": "io/iob_send.c", "output": "iob_send.o", "arguments": [ "clang", "-c", "io/iob_send.c", "-I." ]},
|
||||
|
6
io.h
6
io.h
@ -249,12 +249,16 @@ enum {
|
||||
IOM_WRITE=2,
|
||||
IOM_ERROR=4
|
||||
};
|
||||
/* signal interest in events from a socket */
|
||||
/* return -1 if error, events can be IOM_READ or IOM_WRITE */
|
||||
int iom_add(iomux_t* c,int64 s,unsigned int events);
|
||||
|
||||
/* signal interest in more events from a socket */
|
||||
int iom_requeue(iomux_t* c,int64 s,unsigned int events);
|
||||
|
||||
/* Blocking wait for single event, timeout in milliseconds */
|
||||
/* return -1 if error, 0 if ok; s set to fd, revents set to known events on that fd */
|
||||
/* when done with the fd, call iom_add on it again! */
|
||||
/* when done with the fd, call iom_requeue on it to receive more events! */
|
||||
/* This can be called by multiple threads in parallel */
|
||||
int iom_wait(iomux_t* c,int64* s,unsigned int* revents,unsigned long timeout);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "str.h"
|
||||
#include "iob.h"
|
||||
#include <string.h>
|
||||
#include "iob_internal.h"
|
||||
|
||||
int iob_adds(io_batch* b,const char* s) {
|
||||
return iob_addbuf(b,s,str_len(s));
|
||||
return iob_addbuf(b,s,strlen(s));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "str.h"
|
||||
#include "iob.h"
|
||||
#include <string.h>
|
||||
#include "iob_internal.h"
|
||||
|
||||
int iob_adds_free(io_batch* b,const char* s) {
|
||||
return iob_addbuf_free(b,s,str_len(s));
|
||||
return iob_addbuf_free(b,s,strlen(s));
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "iob.h"
|
||||
#include "iob_internal.h"
|
||||
|
||||
uint64 iob_bytesleft(const io_batch* b) {
|
||||
return b->bytesleft;
|
||||
|
25
io/iob_init.3
Normal file
25
io/iob_init.3
Normal file
@ -0,0 +1,25 @@
|
||||
.TH iob_init 3
|
||||
.SH NAME
|
||||
iob_init \- initialize new I/O batch
|
||||
.SH SYNTAX
|
||||
.B #include <libowfat/iob.h>
|
||||
|
||||
int \fBiob_init\fP(io_batch* b,size_t hint_entries);
|
||||
.SH DESCRIPTION
|
||||
iob_init initializes \fI*b\fR with enough space allocated for
|
||||
\fIhint_entries\fR entries (buffers or files). This is purely a
|
||||
performance hint, if you are unsure just pass 1.
|
||||
|
||||
You can add buffers, strings and files to an I/O batch and then send it
|
||||
all at once using iob_send.
|
||||
|
||||
The benefit of the I/O batch API is that it exploits platform specific
|
||||
APIs like FreeBSD's sendfile. The file contents will always be sent in
|
||||
a way that allows the operating systems to perform zero copy TCP, and
|
||||
the buffers will always be sent using as few syscalls as possible and
|
||||
avoiding unnecessary copying (using writev).
|
||||
.SH "RETURN VALUE"
|
||||
iob_init returns 0 on success. If there was a memory allocation error,
|
||||
it returns -1 instead.
|
||||
.SH "SEE ALSO"
|
||||
iob_new(3), iob_init_autofree(3), iob_reset(3), iob_send(3), iob_addbuf(3), iob_adds_free(3), iob_addfile(3)
|
13
io/iob_init.c
Normal file
13
io/iob_init.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdlib.h>
|
||||
#include "byte.h"
|
||||
#include "iob_internal.h"
|
||||
|
||||
int iob_init(io_batch* b,size_t hint_entries) {
|
||||
byte_zero(b,sizeof(io_batch));
|
||||
if (hint_entries) {
|
||||
if (!array_allocate(&b->b,sizeof(iob_entry),hint_entries))
|
||||
return -1;
|
||||
array_trunc(&b->b);
|
||||
}
|
||||
return 0;
|
||||
}
|
31
io/iob_init_autofree.3
Normal file
31
io/iob_init_autofree.3
Normal file
@ -0,0 +1,31 @@
|
||||
.TH iob_init 3
|
||||
.SH NAME
|
||||
iob_init_autofree \- initialize new I/O batch with autofree flag set
|
||||
.SH SYNTAX
|
||||
.B #include <libowfat/iob.h>
|
||||
|
||||
int \fBiob_init_autofree\fP(io_batch* b,size_t hint_entries);
|
||||
.SH DESCRIPTION
|
||||
iob_init_autofree initializes \fI*b\fR with enough space allocated for
|
||||
\fIhint_entries\fR entries (buffers or files). This is purely a
|
||||
performance hint, if you are unsure just pass 1.
|
||||
|
||||
The autofree flag will be set, which means resources will be freed in
|
||||
\fIiob_send\fR once they have been sent out, not only once you call \fIiob_reset\fR
|
||||
or \fIiob_free\fR at the end. You still have to call those as autofree only
|
||||
frees resources to be sent in the batch, not the resources of the batch
|
||||
itself.
|
||||
|
||||
You can add buffers, strings and files to an I/O batch and then send it
|
||||
all at once using iob_send.
|
||||
|
||||
The benefit of the I/O batch API is that it exploits platform specific
|
||||
APIs like FreeBSD's sendfile. The file contents will always be sent in
|
||||
a way that allows the operating systems to perform zero copy TCP, and
|
||||
the buffers will always be sent using as few syscalls as possible and
|
||||
avoiding unnecessary copying (using writev).
|
||||
.SH "RETURN VALUE"
|
||||
iob_init returns 0 on success. If there was a memory allocation error,
|
||||
it returns -1 instead.
|
||||
.SH "SEE ALSO"
|
||||
iob_new(3), iob_init_autofree(3), iob_reset(3), iob_send(3), iob_addbuf(3), iob_adds_free(3), iob_addfile(3)
|
7
io/iob_init_autofree.c
Normal file
7
io/iob_init_autofree.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "iob_internal.h"
|
||||
|
||||
int iob_init_autofree(io_batch* b,size_t hint_entries) {
|
||||
int r=iob_init(b,hint_entries);
|
||||
b->autofree=1;
|
||||
return r;
|
||||
}
|
@ -4,7 +4,7 @@ iob_new \- create new I/O batch
|
||||
.SH SYNTAX
|
||||
.B #include <libowfat/iob.h>
|
||||
|
||||
io_batch* \fBiob_new\fP(int hint_entries);
|
||||
io_batch* \fBiob_new\fP(size_t hint_entries);
|
||||
.SH DESCRIPTION
|
||||
iob_new creates a new I/O batch with enough space allocated for
|
||||
\fIhint_entries\fR entries (buffers or files). This is purely a
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "byte.h"
|
||||
#include "iob_internal.h"
|
||||
|
||||
io_batch* iob_new(int hint_entries) {
|
||||
io_batch* iob_new(size_t hint_entries) {
|
||||
io_batch* b=(io_batch*)malloc(sizeof(io_batch));
|
||||
if (!b) return 0;
|
||||
byte_zero(b,sizeof(io_batch));
|
||||
|
31
io/iob_new_autofree.3
Normal file
31
io/iob_new_autofree.3
Normal file
@ -0,0 +1,31 @@
|
||||
.TH iob_new_autofree 3
|
||||
.SH NAME
|
||||
iob_new_autofree \- create new I/O batch with autofree flag set
|
||||
.SH SYNTAX
|
||||
.B #include <libowfat/iob.h>
|
||||
|
||||
io_batch* \fBiob_new_autofree\fP(size_t hint_entries);
|
||||
.SH DESCRIPTION
|
||||
iob_new_autofree creates a new I/O batch with enough space allocated for
|
||||
\fIhint_entries\fR entries (buffers or files). This is purely a
|
||||
performance hint. If you are unsure just pass 1.
|
||||
|
||||
The autofree flag will be set, which means resources will be freed in
|
||||
\fIiob_send\fR once they have been sent out, not only once you call \fIiob_reset\fR
|
||||
or \fIiob_free\fR at the end. You still have to call those as autofree only
|
||||
frees resources to be sent in the batch, not the resources of the batch
|
||||
itself.
|
||||
|
||||
You can add buffers, strings and files to an I/O batch and then send it
|
||||
all at once using iob_send.
|
||||
|
||||
The benefit of the I/O batch API is that it exploits platform specific
|
||||
APIs like FreeBSD's sendfile. The file contents will always be sent in
|
||||
a way that allows the operating systems to perform zero copy TCP, and
|
||||
the buffers will always be sent using as few syscalls as possible and
|
||||
avoiding unnecessary copying (using writev).
|
||||
.SH "RETURN VALUE"
|
||||
iob_new_autofree returns a pointer to an I/O batch data structure. If
|
||||
there was a memory allocation error, it returns NULL instead.
|
||||
.SH "SEE ALSO"
|
||||
iob_new(3), iob_init(3), iob_reset(3), iob_send(3), iob_addbuf(3), iob_adds_free(3), iob_addfile(3)
|
8
io/iob_new_autofree.c
Normal file
8
io/iob_new_autofree.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include "iob_internal.h"
|
||||
|
||||
io_batch* iob_new_autofree(size_t hint_entries) {
|
||||
io_batch* b=iob_new(hint_entries);
|
||||
if (b)
|
||||
b->autofree=1;
|
||||
return b;
|
||||
}
|
@ -7,6 +7,14 @@
|
||||
#include "iob_internal.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
__ ___ _
|
||||
\ \ / (_)_ __ __| | _____ _____
|
||||
\ \ /\ / /| | '_ \ / _` |/ _ \ \ /\ / / __|
|
||||
\ V V / | | | | | (_| | (_) \ V V /\__ \
|
||||
\_/\_/ |_|_| |_|\__,_|\___/ \_/\_/ |___/
|
||||
*/
|
||||
|
||||
int64 iob_send(int64 s,io_batch* b) {
|
||||
/* Windows has a sendfile called TransmitFile, which can send one
|
||||
* header and one trailer buffer. */
|
||||
@ -108,6 +116,14 @@ int64 iob_send(int64 s,io_batch* b) {
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
_ _ _
|
||||
| | | |_ __ (_)_ __
|
||||
| | | | '_ \| \ \/ /
|
||||
| |_| | | | | |> <
|
||||
\___/|_| |_|_/_/\_\
|
||||
*/
|
||||
|
||||
#include "havebsdsf.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@ -145,7 +161,7 @@ int64 iob_send(int64 s,io_batch* b) {
|
||||
|
||||
if (b->bytesleft==0) return 0;
|
||||
E=iarray_get(&io_fds,s);
|
||||
if (!E) { errno=EBADF; return -3; }
|
||||
// if (!E) { errno=EBADF; return -3; }
|
||||
last=(iob_entry*)(((char*)array_start(&b->b))+array_bytes(&b->b));
|
||||
v=alloca(b->bufs*sizeof(struct iovec));
|
||||
total=0;
|
||||
@ -167,6 +183,14 @@ int64 iob_send(int64 s,io_batch* b) {
|
||||
}
|
||||
headers=i;
|
||||
#ifdef HAVE_BSDSENDFILE
|
||||
|
||||
/*
|
||||
____ ____ ____
|
||||
| __ ) ___|| _ \
|
||||
| _ \___ \| | | |
|
||||
| |_) |__) | |_| |
|
||||
|____/____/|____/
|
||||
*/
|
||||
if (e+i<last && e[i].type==FROMFILE) {
|
||||
|
||||
#ifdef DEBUGONLINUX
|
||||
@ -212,6 +236,14 @@ eagain:
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
_ _
|
||||
| | (_)_ __ _ ___ __
|
||||
| | | | '_ \| | | \ \/ /
|
||||
| |___| | | | | |_| |> <
|
||||
|_____|_|_| |_|\__,_/_/\_\
|
||||
*/
|
||||
/* Linux has two ways to coalesce sent data; either setsockopt
|
||||
* TCP_CORK or sendto/sendmsg with MSG_MORE. MSG_MORE saves syscalls
|
||||
* in one scenario: when there is n buffers and then possibly one
|
||||
@ -245,7 +277,7 @@ eagain:
|
||||
if (!nozerocopy && sum>=8*1024) {
|
||||
/* MSG_ZEROCOPY has page table management overhead,
|
||||
* it only pays off after 8k or so */
|
||||
if (E->zerocopy==0) {
|
||||
if (E && E->zerocopy==0) {
|
||||
if (setsockopt(s, SOL_SOCKET, SO_ZEROCOPY, (int[]){ 1 },sizeof(int)) == 0) {
|
||||
E->zerocopy=1;
|
||||
ZEROCOPY=MSG_ZEROCOPY;
|
||||
@ -273,9 +305,18 @@ eagain:
|
||||
n = headers-skip; if (n > 50) n=50;
|
||||
for (i=0; i<n; ++i) l += v[skip+i].iov_len;
|
||||
// printf("writing %d records from offset %d, %d bytes\n", skip, n, l);
|
||||
msg.msg_iov=v + skip;
|
||||
msg.msg_iovlen=n;
|
||||
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
|
||||
if (E && E->notsock)
|
||||
notsockwritev:
|
||||
sent=writev(s,v+skip,n);
|
||||
else {
|
||||
msg.msg_iov=v + skip;
|
||||
msg.msg_iovlen=n;
|
||||
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
|
||||
if (sent==-1 && errno==ENOTSOCK) {
|
||||
if (E) E->notsock=1;
|
||||
goto notsockwritev;
|
||||
}
|
||||
}
|
||||
if (sent > 0) totalsent += sent;
|
||||
if (sent == l) continue; // we sent as much as we wanted, go for next batch
|
||||
if (sent >= 0) // we wrote something but not the whole batch
|
||||
@ -294,8 +335,20 @@ eagain:
|
||||
// if we get here, we wrote it all or we got an EAGAIN after
|
||||
// writing something. Treat as regular partial write.
|
||||
sent = totalsent;
|
||||
} else
|
||||
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
|
||||
} else {
|
||||
if (E && E->notsock)
|
||||
notsockwritev2:
|
||||
sent=writev(s,v,headers);
|
||||
else {
|
||||
msg.msg_iov=v;
|
||||
msg.msg_iovlen=headers;
|
||||
sent=sendmsg(s,&msg,MSG_MORE|ZEROCOPY);
|
||||
if (sent==-1 && errno==ENOTSOCK) {
|
||||
if (E) E->notsock=1;
|
||||
goto notsockwritev2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sent==-1) {
|
||||
@ -345,6 +398,11 @@ eagain:
|
||||
for (i=0; e+i<last; ++i) {
|
||||
if (e[i].n<=rest) {
|
||||
rest-=e[i].n;
|
||||
if (b->autofree) {
|
||||
if (e[i].cleanup)
|
||||
e[i].cleanup(e+i);
|
||||
e[i].cleanup=0;
|
||||
}
|
||||
++b->next;
|
||||
if (!rest) break;
|
||||
} else {
|
||||
@ -353,8 +411,10 @@ eagain:
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
io_eagain_write(s);
|
||||
return total;
|
||||
if (b->bytesleft==0) {
|
||||
io_eagain_write(s);
|
||||
return total;
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
abort:
|
||||
|
@ -11,7 +11,7 @@ int64 iob_write2(int64 s,io_batch* b,io_write_callback cb,io_sendfile_callback s
|
||||
total=0;
|
||||
if (!(e=array_get(&b->b,sizeof(iob_entry),b->next)))
|
||||
return -3; /* can't happen error */
|
||||
for (i=0; e+i<last; ++i) {
|
||||
for (i=b->next; e+i<last; ++i) {
|
||||
int thatsit;
|
||||
if (!e[i].n) continue;
|
||||
if (e[i].type==FROMFILE)
|
||||
@ -27,6 +27,13 @@ int64 iob_write2(int64 s,io_batch* b,io_write_callback cb,io_sendfile_callback s
|
||||
total+=sent;
|
||||
b->bytesleft-=sent;
|
||||
if (thatsit) break;
|
||||
// we have sent one full entry
|
||||
if (b->autofree) {
|
||||
if (e[i].cleanup)
|
||||
e[i].cleanup(e+i);
|
||||
e[i].cleanup=0;
|
||||
}
|
||||
++b->next;
|
||||
}
|
||||
if (total == b->bytesleft)
|
||||
iob_reset(b);
|
||||
|
@ -12,12 +12,11 @@ iom_add adds an event you are interested in to an I/O multiplexer.
|
||||
in, and \fIevents\fR is the operation you want to do. It can be IOM_READ
|
||||
or IOM_WRITE.
|
||||
|
||||
If that operation becomes possible on that descriptor, and some thread
|
||||
is calling \fIiom_wait\fR at the time, it will return and tell you the
|
||||
fd and the event.
|
||||
If that operation becomes possible on that descriptor, \fIiom_wait\fR
|
||||
will return and tell you the fd and the event.
|
||||
|
||||
Note that the event registration is removed from the iomux_t context if
|
||||
it occurs. You will have to call \fIiom_wait\fR again after you handled
|
||||
it occurs. You will have to call \fIiom_requeue\fR after you handled
|
||||
the event, if you are still interested in it.
|
||||
|
||||
Closing a file descriptor with registered events will discard the event
|
||||
@ -30,4 +29,4 @@ step.
|
||||
.SH "RETURN VALUE"
|
||||
iom_add returns 0 on success and -1 on error, setting errno.
|
||||
.SH "SEE ALSO"
|
||||
iom_init, iom_wait, iom_abort
|
||||
iom_init, iom_requeue, iom_wait, iom_abort
|
||||
|
35
io/iom_requeue.3
Normal file
35
io/iom_requeue.3
Normal file
@ -0,0 +1,35 @@
|
||||
.TH iom_requeue 3
|
||||
.SH NAME
|
||||
iom_requeue \- re-add event to I/O multiplexer
|
||||
.SH SYNTAX
|
||||
.B #include <libowfat/io.h>
|
||||
|
||||
int \fBiom_requeue\fP(iomux_t* c, int64 fd, unsigned int events);
|
||||
.SH DESCRIPTION
|
||||
iom_requeue adds an event you are interested in to an I/O multiplexer.
|
||||
|
||||
\fIfd\fR is the file descriptor (usually a socket) you are interested
|
||||
in, and \fIevents\fR is the operation you want to do. It can be IOM_READ
|
||||
or IOM_WRITE.
|
||||
|
||||
If that operation becomes possible on that descriptor, \fIiom_wait\fR
|
||||
will return and tell you the fd and the event.
|
||||
|
||||
Note that the event registration is removed from the iomux_t context if
|
||||
it occurs. You will have to call \fIiom_requeue\fR again if you are
|
||||
interested in more events for this descriptor. Do this only after you
|
||||
are done handling this event, otherwise \fIiom_wait\fR might indicate a
|
||||
new event to another thread while this thread is still working on the
|
||||
descriptor, leading to unexpected behavior.
|
||||
|
||||
Closing a file descriptor with registered events will discard the event
|
||||
registration.
|
||||
|
||||
.SH "LINKING"
|
||||
You may have to add \fI-lpthread\fR to the command line in the linking
|
||||
step.
|
||||
|
||||
.SH "RETURN VALUE"
|
||||
iom_requeue returns 0 on success and -1 on error, setting errno.
|
||||
.SH "SEE ALSO"
|
||||
iom_init, iom_add, iom_wait, iom_abort
|
28
io/iom_requeue.c
Normal file
28
io/iom_requeue.c
Normal file
@ -0,0 +1,28 @@
|
||||
#include "io_internal.h"
|
||||
#ifdef HAVE_EPOLL
|
||||
#include <sys/epoll.h>
|
||||
#endif
|
||||
#ifdef HAVE_KQUEUE
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
int iom_requeue(iomux_t* c,int64 s,unsigned int events) {
|
||||
#ifdef HAVE_EPOLL
|
||||
struct epoll_event e = { .events=EPOLLONESHOT, .data.fd=s };
|
||||
if (events & IOM_READ) e.events|=EPOLLIN;
|
||||
if (events & IOM_WRITE) e.events|=EPOLLOUT;
|
||||
return epoll_ctl(c->ctx, EPOLL_CTL_MOD, s, &e);
|
||||
#elif defined(HAVE_KQUEUE)
|
||||
struct kevent kev;
|
||||
struct timespec ts = { 0 };
|
||||
EV_SET(&kev, s,
|
||||
(events & IOM_READ ? EVFILT_READ : 0) +
|
||||
(events & IOM_WRITE ? EVFILT_WRITE : 0),
|
||||
EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, (void*)s);
|
||||
return kevent(c->ctx, &kev, 1, 0, 0, &ts);
|
||||
#else
|
||||
#warning "only epoll and kqueue supported for now"
|
||||
#endif
|
||||
}
|
@ -3,10 +3,10 @@
|
||||
#ifdef HAVE_EPOLL
|
||||
#include <sys/epoll.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#ifdef HAVE_KQUEUE
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#ifdef __dietlibc__
|
||||
@ -15,7 +15,7 @@
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
// return the next event, waiting of none are queued
|
||||
// return the next event, waiting if none are queued
|
||||
// wait at most timeout milliseconds
|
||||
// on success, return 1 and return the fd in *s and the events on it in *revents
|
||||
// if we waited but ran into a timeout, return 0
|
||||
@ -171,19 +171,40 @@ int iom_wait(iomux_t* c,int64* s,unsigned int* revents,unsigned long timeout) {
|
||||
} else {
|
||||
/* somebody else has the job to fill the queue */
|
||||
struct timespec ts;
|
||||
ts.tv_sec = timeout / 1000;
|
||||
ts.tv_nsec = (timeout % 1000) * 1000000;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
tv.tv_sec += timeout/1000;
|
||||
tv.tv_usec += timeout%1000;
|
||||
if (tv.tv_usec>1000000) {
|
||||
tv.tv_usec-=1000000;
|
||||
++tv.tv_sec;
|
||||
}
|
||||
ts.tv_sec = tv.tv_sec;
|
||||
ts.tv_nsec = tv.tv_usec * 1000;
|
||||
#ifdef __dietlibc__
|
||||
r=cnd_timedwait(&c->sem,&c->mtx,&ts);
|
||||
switch (r) {
|
||||
case thrd_success:
|
||||
continue;
|
||||
case thrd_timedout:
|
||||
return 0;
|
||||
case thrd_error:
|
||||
return -1;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
r=pthread_cond_timedwait(&c->sem,&c->mtx,&ts);
|
||||
switch (r) {
|
||||
case 0: continue;
|
||||
case ETIMEDOUT: return 0;
|
||||
default: return -1;
|
||||
}
|
||||
#else
|
||||
r=sem_timedwait(&c->sem,&ts);
|
||||
#endif
|
||||
if (r==-1) {
|
||||
if (errno==ETIMEDOUT) return 0;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/* fall through into next loop iteration */
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ typedef struct {
|
||||
unsigned int closed:1; /* io_close called, but close deferred because of outstanding events */
|
||||
unsigned int zerocopy:1; /* linux: setsockopt SO_ZEROCOPY done */
|
||||
unsigned int goterror:1; /* got POLLERR|POLLHUP */
|
||||
unsigned int notsock:1; /* linux: got ENOTSOCKET from sendmsg, use writev */
|
||||
#ifdef __MINGW32__
|
||||
unsigned int readqueued:2;
|
||||
unsigned int writequeued:2;
|
||||
|
51
iob.h
51
iob.h
@ -21,34 +21,83 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* you should not have to touch any of the internals */
|
||||
typedef struct io_batch {
|
||||
/* array of iob_entry, defined in iob_internal.h */
|
||||
array b;
|
||||
/* bytes left in the batch (starts as sum of lengths of all iob_entries */
|
||||
uint64 bytesleft;
|
||||
/* next is the index of the first unsent batch in the array */
|
||||
long next,bufs,files;
|
||||
/* Ask iob_send to free entries from the array as we go.
|
||||
* Usually when iob_send returns 0 or error, you call iob_reset.
|
||||
* You still have to call iob_reset even with this flag set, as
|
||||
* autofree operates on the buffers in the array but does not free the
|
||||
* array itself */
|
||||
int autofree;
|
||||
} io_batch;
|
||||
|
||||
io_batch* iob_new(int hint_entries);
|
||||
/* Initialize an io_batch. Return 0 on success, -1 on malloc failure for
|
||||
* embedded array */
|
||||
int iob_init(io_batch* b,size_t hint_entries);
|
||||
/* initialize an io_batch that auto-frees entries as soon as
|
||||
* iob_send/iob_write have written them. Return 0 on success, -1 on
|
||||
* malloc failure for embedded array */
|
||||
int iob_init_autofree(io_batch* b,size_t hint_entries);
|
||||
|
||||
/* malloc and initialize an io_batch */
|
||||
io_batch* iob_new(size_t hint_entries);
|
||||
/* malloc and initialize an io_batch that auto-frees entries as soon as
|
||||
* iob_send/iob_write have written them */
|
||||
io_batch* iob_new_autofree(size_t hint_entries);
|
||||
|
||||
/* queue buffer in io_batch */
|
||||
att_readn(2,3)
|
||||
int iob_addbuf(io_batch* b,const void* buf,uint64 n);
|
||||
|
||||
/* queue buffer in io_batch, and give ownership to batch. */
|
||||
/* the io_batch functions will take care of freeing it. */
|
||||
att_readn(2,3)
|
||||
int iob_addbuf_free(io_batch* b,const void* buf,uint64 n);
|
||||
|
||||
/* queue mmapped memory reagion in io_batch, and give ownership to batch. */
|
||||
/* the io_batch functions will take care of unmapping it. */
|
||||
att_readn(2,3)
|
||||
int iob_addbuf_munmap(io_batch* b,const void* buf,uint64 n);
|
||||
|
||||
/* queue asciiz string in io_batch. */
|
||||
att_read(2)
|
||||
int iob_adds(io_batch* b,const char* s);
|
||||
|
||||
/* queue asciiz string in io_batch, and give ownership to batch. */
|
||||
/* the io_batch functions will take care of freeing it. */
|
||||
att_read(2)
|
||||
int iob_adds_free(io_batch* b,const char* s);
|
||||
|
||||
/* queue file contents in io_batch. */
|
||||
int iob_addfile(io_batch* b,int64 fd,uint64 off,uint64 n);
|
||||
|
||||
/* queue file contents in io_batch, and give ownership to batch */
|
||||
/* the io_batch functions will take care of closing it. */
|
||||
int iob_addfile_close(io_batch* b,int64 fd,uint64 off,uint64 n);
|
||||
|
||||
/* send (rest of) io_batch over socket s */
|
||||
/* return number of bytes written.
|
||||
* return 0 means whole batch written successfully.
|
||||
* return -1 means couldn't write more on non-blocking socket, try again later
|
||||
* return -3 means error (errno set) */
|
||||
int64 iob_send(int64 s,io_batch* b);
|
||||
/* same as iob_send but don't use callback instead of write and
|
||||
* sendfile. Use this to write via OpenSSL or so */
|
||||
int64 iob_write(int64 s,io_batch* b,io_write_callback cb);
|
||||
/* same as iob_write if the TLS library also has a sendfile function */
|
||||
int64 iob_write2(int64 s,io_batch* b,io_write_callback cb,io_sendfile_callback sfcb);
|
||||
|
||||
/* iob_reset closes files and frees buffer in the io_batch, and the
|
||||
* array with the buffer, but not the batch itself (in case it's a local
|
||||
* variable and not malloced) */
|
||||
void iob_reset(io_batch* b);
|
||||
/* iob_free does iob_reset but also frees the batch itself */
|
||||
void iob_free(io_batch* b);
|
||||
void iob_prefetch(io_batch* b,uint64 bytes);
|
||||
uint64 iob_bytesleft(const io_batch* b);
|
||||
|
14
test/iob.c
14
test/iob.c
@ -1,7 +1,7 @@
|
||||
#include <assert.h>
|
||||
#include "iob.h"
|
||||
#include "buffer.h"
|
||||
#include "libowfat/iob.h"
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
static int64 write_cb(int64 fd,const void* buf,uint64 len) {
|
||||
if (len>2) len=2;
|
||||
@ -11,14 +11,16 @@ static int64 write_cb(int64 fd,const void* buf,uint64 len) {
|
||||
int main() {
|
||||
int64 fd;
|
||||
io_batch* b;
|
||||
int64 r;
|
||||
char* fnord=strdup(" fnord\n");
|
||||
assert(fnord);
|
||||
assert(io_readfile(&fd,"GNUmakefile"));
|
||||
assert(b=iob_new(10));
|
||||
assert((b=iob_new_autofree(10)));
|
||||
assert(iob_addbuf(b,"Huhu",4));
|
||||
assert(iob_addbuf(b," fnord\n",7));
|
||||
assert(iob_addbuf_free(b,fnord,7));
|
||||
assert(iob_addfile(b,fd,10,10));
|
||||
iob_send(1,b);
|
||||
#if 1
|
||||
#if 0
|
||||
int64 r;
|
||||
do {
|
||||
r=iob_write(1,b,write_cb);
|
||||
} while (r>0);
|
||||
|
@ -14,7 +14,7 @@ int worker(void* arg) {
|
||||
uintptr_t i=(uintptr_t)arg;
|
||||
char buf[100];
|
||||
int64 s;
|
||||
int events;
|
||||
unsigned int events;
|
||||
|
||||
write(1,buf,sprintf(buf,"starting thread %ld\n",i));
|
||||
|
||||
@ -73,7 +73,10 @@ int main() {
|
||||
if (thrd_join(x[i],&r)==-1)
|
||||
#else
|
||||
void* tmp;
|
||||
if (pthread_join(x[i],&tmp)==-1, r=(int)(uintptr_t)tmp)
|
||||
|
||||
if (pthread_join(x[i],&tmp)!=-1)
|
||||
r=(int)(uintptr_t)tmp;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
perror("thrd_join");
|
||||
@ -82,5 +85,7 @@ int main() {
|
||||
printf("thread %d returned %d\n",i,r);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
85
test/iomcli.c
Normal file
85
test/iomcli.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include <libowfat/socket.h>
|
||||
#include <libowfat/io.h>
|
||||
#include <libowfat/errmsg.h>
|
||||
#include <libowfat/ip6.h>
|
||||
#include <libowfat/fmt.h>
|
||||
#include <libowfat/scan.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <threads.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
iomux_t iom;
|
||||
int s[32];
|
||||
atomic_int n;
|
||||
|
||||
#define TRANSACTIONS 100000
|
||||
|
||||
int w(void* a) {
|
||||
(void)a;
|
||||
for (;;) {
|
||||
int64 s;
|
||||
unsigned int events;
|
||||
switch (iom_wait(&iom,&s,&events,1000)) {
|
||||
case -1:
|
||||
diesys(111,"iom_wait");
|
||||
break;
|
||||
case 0:
|
||||
carp("iom_wait: timeout");
|
||||
break;
|
||||
case 1:
|
||||
if (events&IOM_WRITE) {
|
||||
if (write(s,"salut!\n",7) != 7)
|
||||
diesys(111,"write");
|
||||
if (iom_requeue(&iom,s,IOM_READ) == -1)
|
||||
diesys(111,"iom_requeue");
|
||||
} else {
|
||||
char buf[100];
|
||||
ssize_t r=read(s,buf,sizeof buf);
|
||||
if (r<=0 || atomic_fetch_add(&n,1) >= TRANSACTIONS) {
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
if (iom_requeue(&iom,s,IOM_WRITE) == -1)
|
||||
diesys(111,"iom_requeue");
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc,char* argv[]) {
|
||||
iom_init(&iom);
|
||||
for (unsigned int i=0; i<sizeof(s)/sizeof(s[0]); ++i) {
|
||||
s[i]=socket_tcp6b();
|
||||
errmsg_iam("iomcli");
|
||||
if (s[i]==-1)
|
||||
diesys(111,"socket");
|
||||
if (socket_connect6(s[i],V6loopback,8000,0)==-1 && errno!=EINPROGRESS)
|
||||
diesys(111,"connect");
|
||||
if (iom_add(&iom,s[i],IOM_WRITE)==-1)
|
||||
diesys(111,"iom_add");
|
||||
}
|
||||
|
||||
thrd_t t[32];
|
||||
unsigned int nthr=1;
|
||||
if (argc>1 && scan_uint(argv[1],&nthr)>0) {
|
||||
if (nthr>sizeof(t)/sizeof(t[0])) {
|
||||
char buf[FMT_LONG];
|
||||
buf[fmt_ulong(buf,sizeof(t)/sizeof(t[0]))]=0;
|
||||
die(111,"max threads > ",buf);
|
||||
}
|
||||
}
|
||||
for (unsigned int i=0; i<nthr; ++i) {
|
||||
if (thrd_create(&t[i],w,0)!=thrd_success)
|
||||
die(111,"thread creation failed");
|
||||
}
|
||||
|
||||
for (unsigned int i=0; i<nthr; ++i) {
|
||||
int retval;
|
||||
if (thrd_join(t[i],&retval)!=thrd_success)
|
||||
die(111,"thread join failed");
|
||||
}
|
||||
return 0;
|
||||
}
|
114
test/iomsrv.c
Normal file
114
test/iomsrv.c
Normal file
@ -0,0 +1,114 @@
|
||||
#include <libowfat/socket.h>
|
||||
#include <libowfat/io.h>
|
||||
#include <libowfat/errmsg.h>
|
||||
#include <libowfat/ip6.h>
|
||||
#include <libowfat/fmt.h>
|
||||
#include <libowfat/scan.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <threads.h>
|
||||
|
||||
iomux_t iom;
|
||||
|
||||
void read_data_from_socket(int s) {
|
||||
char buf[1024];
|
||||
ssize_t r=read(s,buf,sizeof buf);
|
||||
if (r==-1) {
|
||||
r=fmt_str(buf,"I/O error from fd ");
|
||||
r+=fmt_ulong(buf+r,s);
|
||||
buf[r]=0;
|
||||
carpsys(buf);
|
||||
close(s);
|
||||
return;
|
||||
}
|
||||
if (r==0) {
|
||||
close(s);
|
||||
return;
|
||||
}
|
||||
/* we'd usually have some protocol parsing here but for this
|
||||
* simplistic test program we'll just accept any input as valid
|
||||
* request */
|
||||
if (iom_requeue(&iom,s,IOM_WRITE)!=0) {
|
||||
carpsys("iom_requeue");
|
||||
close(s);
|
||||
}
|
||||
}
|
||||
|
||||
void write_data_to_socket(int s) {
|
||||
if (write(s,"hello, world!\n",14) != 14) {
|
||||
carpsys("write");
|
||||
close(s);
|
||||
}
|
||||
if (iom_requeue(&iom,s,IOM_READ)!=0) {
|
||||
carpsys("iom_requeue");
|
||||
close(s);
|
||||
}
|
||||
}
|
||||
|
||||
int w(void* a) {
|
||||
int servsock=*(int*)a;
|
||||
for (;;) {
|
||||
int64 s;
|
||||
unsigned int events;
|
||||
switch (iom_wait(&iom,&s,&events,1000)) {
|
||||
case -1:
|
||||
diesys(111,"iom_wait");
|
||||
break;
|
||||
case 0:
|
||||
carp("iom_wait: timeout");
|
||||
break;
|
||||
case 1:
|
||||
if (s==servsock) {
|
||||
char ip[16];
|
||||
uint16 port;
|
||||
uint32 scope_id;
|
||||
int conn=socket_accept6(s,ip,&port,&scope_id);
|
||||
if (conn==-1)
|
||||
diesys(111,"accept");
|
||||
if (iom_add(&iom,conn,IOM_READ)==-1)
|
||||
diesys(111,"iom_add");
|
||||
if (iom_requeue(&iom,s,IOM_READ)==-1)
|
||||
diesys(111,"iom_requeue");
|
||||
} else if (events&IOM_READ)
|
||||
read_data_from_socket(s);
|
||||
else
|
||||
write_data_to_socket(s);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc,char* argv[]) {
|
||||
int servsock=socket_tcp6();
|
||||
errmsg_iam("iomsrv");
|
||||
if (servsock==-1)
|
||||
diesys(111,"socket");
|
||||
if (socket_bind6_reuse(servsock,V6loopback,8000,0)==-1)
|
||||
diesys(111,"bind to localhost:8000");
|
||||
if (socket_listen(servsock,16)==-1)
|
||||
diesys(111,"listen");
|
||||
iom_init(&iom);
|
||||
if (iom_add(&iom,servsock,IOM_READ)==-1)
|
||||
diesys(111,"iom_add");
|
||||
|
||||
thrd_t t[32];
|
||||
unsigned int nthr=1;
|
||||
if (argc>1 && scan_uint(argv[1],&nthr)>0) {
|
||||
if (nthr>sizeof(t)/sizeof(t[0])) {
|
||||
char buf[FMT_LONG];
|
||||
buf[fmt_ulong(buf,sizeof(t)/sizeof(t[0]))]=0;
|
||||
die(111,"max threads > ",buf);
|
||||
}
|
||||
}
|
||||
for (unsigned int i=0; i<nthr; ++i) {
|
||||
if (thrd_create(&t[i],w,(void*)&servsock)!=thrd_success)
|
||||
die(111,"thread creation failed");
|
||||
}
|
||||
|
||||
for (unsigned int i=0; i<nthr; ++i) {
|
||||
int retval;
|
||||
if (thrd_join(t[i],&retval)!=thrd_success)
|
||||
die(111,"thread join failed");
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user