4 ms·
IDK it seems pretty common in the embedded world to add support for a new piece of hardware by copying the entire driver and then changing the parts that the ne
by est31 6y ago
IDK it seems pretty common in the embedded world to add support for a new piece of hardware by copying the entire driver and then changing the parts that the new hardware supports instead of trying to come up with a driver that supports all generations of the hardware. Pretty sad if you ask me and very unmaintainable, but, at least if you ask the companies, people should just buy newer generations of their hardware if they want those bugfixes :).
- rictic 6y agoWild speculation from someone who doesn't do hardware, but I'd guess that it's not so much writing the software as testing it that motivates that. It'd be hard to keep the testing matrix of apps X hardware X driver version from exploding out of control. Your customers will be hella pissed at you if their favorite game suddenly doesn't work on their system after a driver update. So you need to test a representative sample of previously-working software across all hardware that the updated driver applies to. That sounds like a nightmare, and a capital-intensive one because you need to keep machines up with all of these cards, both in continuous integration and for interactive debugging. I can understand the impulse to keep the list of hardware that new driver versions support small.
- deleted 6y ago[deleted]
- colonwqbang 6y agoThis is the real reason in my experience, combined with the bringup/support cycle that comes with hardware development. If you fork the driver for bringup, you buy yourself a lot of freedom to change things. During support phase, when the hardware is already in the hands of the customer, changing things is more risky and so you have to be conservative. For example, maybe you had a chip bug in the previous hardware generation which caused the system to hang after several days of stress testing. You found a software workaround for the bug, but every time you touch the code you need to re-verify the workaround, which takes days. Of course, the downsides of forking the code are also very apparent...
- gsnedders 6y agoAnother example of this in the kernel is filesystems: in theory, the ext4 driver can read/write ext2/ext3 filesystems fine. And yet the kernel for years had ext2, ext3, and ext4 implementations, each later version derived from the previous. The ext3 driver was eventually removed in 2015, but ext2 and ext4 survive.
- aspaceman 6y agoYeah exactly. Every new driver at AMD and NVIDIA have to fill a massive spreadsheet with most major game benchmarks from the last 5 years. Along with a collection of particularly nasty games.
- oblio 6y agoThe thing is, DRY has some downsides. If you've pretty much nailed down the functionality of the old thing, especially if it involves some kind of manual testing/open beta test with users, the last thing you want to do is touch the old code. I'm not defending them, but sometimes something is good enough and you have to move on.
- reader_mode 6y agoThis doesn't sound like an issue with DRY as much as an issue of monolithic design. If driver version X worked but X+1 doesn't on your driver - don't update the driver. But when the driver is in the kernel trunk then that option isn't that simple.
- atq2119 6y agoIn the context of the Linux kernel, you've never truly nailed down the functionality of the old thing. Interfaces external to the driver evolve over time (which bleeds into changes internal to the driver), requirements change, people want to add new features that old hardware ought to support -- all this adds up and puts evolutionary pressure on the drivers. Code duplication really hurts here. It's possible that the AMD developers are from a Windows culture where they don't have to worry about this because Microsoft gives them a stable interface. Though even there, I find it questionable whether it's a win. Surely the occasional bug will surface that affects drivers for older hardware as well?
- barumi 6y ago> IDK it seems pretty common in the embedded world to add support for a new piece of hardware by copying the entire driver and then changing the parts that the new hardware supports instead of trying to come up with a driver that supports all generations of the hardware. The rule of three is not exclusive to the embedded world. It´s far better to have duplicate code around then to have to deal with poor generalizations that affect multiple independent modules, which in this case mean hardware support. To put it in perspective, how many pieces of hardware would you require to re-test and validate if you decided to refactor bits of drivers that might share a common code path?
- gavinray 6y agoThis might not exist in C (I've never written it), but something like this seems like a fairly clean pattern you could use: abstract class BaseDriver { abstract commonThing() } abstract class BaseDriverV1 extends BaseDriver { commonThing() { console.log('This is the common method implementation for all V1 drivers') } abstract doThingOnlyV1Does() } class DriverV1_1 extends BaseDriverV1 { doThingOnlyV1Does() { console.log('This is how Driver V1.1 does the V1 thing') } } This way you can use either an interface or an "abstract" definition that declares the base driver methods and the versioned driver methods, then provide version-dependent implementations where needed, or else share the common implementations by inheritance/extension. Maybe this turns into spaghetti at scale and it actually is easier to just copy-paste all of it, who knows.
- barumi 6y ago> This might not exist in C (I've never written it), but something like this seems like a fairly clean pattern you could use: How sure are you? I mean, if the code path of a driver is touched, that triggers all verification and validation steps on all pieces of hardware that are required to ensure that the pieces of hardware affected by it will continue to work as expected. Furthermore, how many bugs are introduced on a daily basis because people like you and me push "fairly clean patterns" that end up triggering all sorts of unexpected consequences? I know I did, and still do, my share.
- 6y ago
- qppo 6y agoI don't know, to me this is a bit like taking two c programs that print "hello world" and "goodbye world", looking at the assembly that is compiled then remarking "pretty sad and very unmaintainable." Point being, maintain the code generator and not the generated code.
- ptx 6y agoRight. But here the generated code is checked into the source tree and the code generator is kept proprietary, which is why it's sad and unmaintainable.
- unionpivo 6y agoCode generator probably runs of their verilog/hdl source of the chips. It probably relies (or is build on top of) on proprietary EDA tools. Without open sourcing their chips, it would probably be useless. Even if you work for chip maker, that is what you usually get from hardware guys, so we are probably getting the same as AMD own driver programmers. \s Welcome to wonderful world of driver development at majority of hardware houses \s
- ptx 6y agoThey could still separate the extraction of the data (keeping it proprietary) from the code generation. The latter could work off of the extracted data kept in a more sensible format.
- notanotherycomb 6y agoThat's how we do things at work. If we need to change a class function we outright copy/paste it then change what we need. This is so everything is backwards compatible. A bug in one version might be expected or documented in a previous. We can't fix the bug in an older version unless we get the OK from our clients because they might be depending/expecting it for their code to run correctly It's a good system. You shouldn't complain. And deleting code is easy since not everything depends on everything