<GitHub17>
[artiq] whitequark force-pushed rust from 3e2fbac to 4c6cad2: https://git.io/v6r2e
<GitHub17>
artiq/rust 4c6cad2 whitequark: Add a Rust component in the runtime.
<whitequark>
bb-m-labs: force build --branch=rust artiq
<bb-m-labs>
build forced [ETA 26m39s]
<bb-m-labs>
I'll give a shout when the build finishes
<rjo>
whitequark: ha. nice.
<rjo>
one thing about rust that i like is the numerics people toying with BLIS and re-thinking those libraries.
<rjo>
sb0, whitequark: do we informally agree that we'll try never to force-push to artiq master?
<whitequark>
rjo: we can enforce that with github, by the way.
<whitequark>
I have force-pushed master in the past when I noticed some stupid mistake right after commit. but I have no strong objection to getting rid of force-pushing.
<whitequark>
ok, that wasn't the *only* linker bug.
<whitequark>
binutils make me sad.
<whitequark>
the worst part is how annoying it is to debug these. compiler bugs are at least localized, and easily fixable. linker bugs spread bad data all around the binary.
<whitequark>
hm, that might have been a single or1k bug after all...
<sb0>
rjo, any thoughts about integrating artiq_master and artiq_ctlmgr with the OS services mechanisms (e.g. systemd) to get them to run automatically at boot?
<whitequark>
I was under impression that you expected rust to supplment C runtime, not replace it, from some earlier discussion
<whitequark>
but ok. we can do either. I was going to replace it part-by-part anyway, and not one large rewrite.
<sb0>
15 emails and one phone call later, I have a WAWF account. bureaucracy FTW.
<whitequark>
this is a good reason to keep it in master as well, so that it will get more testing.
<sb0>
what I mostly want is replace the current buggy/messy TCP/IP code with a cleaner asyncio-style implementation
<sb0>
but this is a good opportunity to clean up other parts, such as move dds.c into ARTIQ-Python
<sb0>
ditch the bridge, which becomes unnecessary after that; since there will be a low-level DDS API exposed, this can be done from python
<whitequark>
ok
<whitequark>
although I must say I still don't understand why you insist on asynchronous handling of TCP/IP specifically.
<whitequark>
there are just as many (or as few, depending on how helpful tools are) concurrency bugs, and some additional complexity that will never pay off on the core device, where you'll never have ten connections, much less ten thousands
<sb0>
with the current code, how do you close a connection with a error reported to the user?
<whitequark>
right now, i am going to use libfringe, which is a stackful coroutine library. in essence this is just regular threads, except with context switching that isn't assisted by kernel/CPU, but rather is done fully in usermode
<whitequark>
hm
<whitequark>
with the current code? not sure. does it do anything special?
<whitequark>
need to do*
<sb0>
well there's only one TCP output buffer, so you are blocking on the connection with tcp_output() until the receiver acks them
<sb0>
and then close.
<whitequark>
yes. but only the thread that wants to output will block.
<sb0>
there are no threads right now, so this blocks the whole system
<whitequark>
yes.
<whitequark>
my question is specifically why you insist on asyncio versus... just threads
<whitequark>
asyncio uses a very specific model
<sb0>
threads are more complicated
<whitequark>
really??
<sb0>
yes.
<whitequark>
citation needed
<sb0>
my personal experience
<rjo>
sb0: absolutely. that's extremely useful. but also windows. only nasty thing is to juggle different conda envs on the same machine, different package revisions with the service file in /etc ...
<sb0>
locking is much simpler with asyncio, since as long as you don't yield, you are not preempted
<whitequark>
yes. these userspace threads I'm talking about are not preemptible.
<whitequark>
(well, by definition; you need CPU support to preempt)
<sb0>
so it's like asyncio, without coroutines?
<sb0>
i.e. only i/o functions may preempt
<rjo>
whitequark: i think github has something (partially) like homu already.
<whitequark>
sb0: the threading library (or generator library, same thing here) itself doesn't care.
<whitequark>
you have a thing you can call `yield` on, which will swap you out
<whitequark>
in practice, i'll wrap that in some code that adds plumbing to use lwip
<rjo>
whitequark: does buildbot handle service buildmaster restart while slaves are running/building?
<whitequark>
yielder.yield(WaitForLwipInput(...)), you get the idea
<whitequark>
rjo: it kills the builds.
bb-m-labs has quit [Quit: buildmaster reconfigured: bot disconnecting]
<rjo>
whitequark: ok.
<sb0>
okay, that's fine too.
bb-m-labs has joined #m-labs
<whitequark>
sb0: there's a massive benefit, which is you don't have to add an IO monad, like asyncio-style code requires
<sb0>
can you cancel a task?
<whitequark>
the function signatures stay unmolested, there is no need for complicated FSM generators that will bloat your code size and compile time, etc
<whitequark>
yes. you can forcibly unwind a thread.
<whitequark>
Rust doesn't have exceptions, only panics. the difference is that you don't need to care about exception safety, because panics can only be caught at thread boundaries.
<whitequark>
i.e. you can never observe data in a half-baked state, left there by an exception that broke through some code
<sb0>
okay. so when a task gets cancelled by another one, it can still attempt to write some error message to the TCP connection it is managing before closing the connection and dying?
<whitequark>
sure. a destructor can take care of that.
<whitequark>
but there are other ways to handle that anyway. another task could grab the TCP stream and write there (for example).
<whitequark>
we have the unwinder in the core device working anyway, so spending time on it a year ago worked out quite well
<sb0>
bah, yes, but then all the error message generating code has to go into that task that deals with broken connections
<sb0>
the model "one tasks is responsible for one connection" keeps things better organized
<sb0>
also. the moninj code that uses UDP right now should be replaced by something TCP-based
<whitequark>
I think in this case doing this via panics is a bad idea, it's much better to return an error code from the "system call"
<whitequark>
something like EINTR
<whitequark>
and then it would bubble up in the task through IoResult
<sb0>
ok.
<whitequark>
panics are generally reserved for truly exceptional conditions. broken invariants.
<sb0>
things that should be interruptible are TCP/IP operations, waiting on kernel-CPU messages, and maybe timers
<whitequark>
any sort of wait would be interruptible. no real problem with that.
<sb0>
ok
<whitequark>
it's very elegant in Rust. you can do something like
<whitequark>
timer.wait(1.0)?;
<whitequark>
the ? expands into `match timer.wait(1.0) { Ok(()) => ... continue..., Err(e) => return e }
<sb0>
good.
<sb0>
rjo, why is the command for registering 7-series FPGAs called "pld device virtex2"?