UDI, EDI, CDI Which do you use and why
UDI, EDI, CDI Which do you use and why
Hi im currently re-working on my module loader to be compatible with other hobby os and I honestly don't know which one to implement i started with cdi but couldnt find enough info on it... So what do you use in your os and why?
- thepowersgang
- Member
- Posts: 734
- Joined: Tue Dec 25, 2007 6:03 am
- Libera.chat IRC: thePowersGang
- Location: Perth, Western Australia
- Contact:
Re: UDI, EDI, CDI Which do you use and why
Most of my loadable modules are native modules, but I have a (nearly) fully working UDI implementation.
Of the "common" device interfaces, I prefer UDI, because it has had the most work put into it. It is relatively complex to get started with, but it is the most extensible of the interfaces. (That said, it lacks a proper graphics binding, though someone was working on one).
EDI is dead as far as I know (and had some glaring holes in it), I've never worked with CDI, but I think it was quite a bit better (just nowhere as cross-platform as UDI)
Of the "common" device interfaces, I prefer UDI, because it has had the most work put into it. It is relatively complex to get started with, but it is the most extensible of the interfaces. (That said, it lacks a proper graphics binding, though someone was working on one).
EDI is dead as far as I know (and had some glaring holes in it), I've never worked with CDI, but I think it was quite a bit better (just nowhere as cross-platform as UDI)
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Re: UDI, EDI, CDI Which do you use and why
UDI is the heavy-weight professional solution that covers probably most requirements that you could think of and it comes with the corresponding complexity.
CDI is the "just a hobby, won't big and professional like UDI" thing that has simple interfaces with less features and is therefore quite easy to understand and implement. It is still extensible, because unlike UDI it doesn't guarantee strict API and especially ABI stability (binary compatibility between OSes isn't a goal for CDI), so if you need more at some point, you can probably do it.
The two main reasons why I started CDI with some other hobby OS developers is that UDI was too complex for my needs, and that I couldn't find any free drivers to use for the standard components like IDE, rtl8139, etc. Not sure if anything has changed with UDI, but with CDI we tried to create a central repository of free drivers - which might not be that large yet, but it's more useful for my hobby OSes than anything that I've seen for UDI so far.
As for information, you probably know the Doxygen docs, which I'll freely admit are still lacking. Basically the approach for implementing it is checking out the CDI repository, choosing a driver and implementing functions from the header files until it builds. Then make sure you call the init function of the driver and the devices it detected and that's it. I think network drivers are the easiest for the start, or possibly storage.
CDI is the "just a hobby, won't big and professional like UDI" thing that has simple interfaces with less features and is therefore quite easy to understand and implement. It is still extensible, because unlike UDI it doesn't guarantee strict API and especially ABI stability (binary compatibility between OSes isn't a goal for CDI), so if you need more at some point, you can probably do it.
The two main reasons why I started CDI with some other hobby OS developers is that UDI was too complex for my needs, and that I couldn't find any free drivers to use for the standard components like IDE, rtl8139, etc. Not sure if anything has changed with UDI, but with CDI we tried to create a central repository of free drivers - which might not be that large yet, but it's more useful for my hobby OSes than anything that I've seen for UDI so far.
As for information, you probably know the Doxygen docs, which I'll freely admit are still lacking. Basically the approach for implementing it is checking out the CDI repository, choosing a driver and implementing functions from the header files until it builds. Then make sure you call the init function of the driver and the devices it detected and that's it. I think network drivers are the easiest for the start, or possibly storage.
Re: UDI, EDI, CDI Which do you use and why
So in a nutshell i should start off with an easy interface such as cdi then when i need more power and portability then implement udi. Also, out of curiosity, what glaring holes does edi have in it since i see you have implemented it in your kernel (acess2)
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: UDI, EDI, CDI Which do you use and why
UDI is the powerhouse of the lot, but doesn't have that much drivers unfortunately because it's more complicated. I have a fair bit of it implemented though.
CDI is ok for unix clones, but it needs some horrible hacks to use in an asynchronous message passing userspace to the extent that I decided against it. In comparison, UDI is fully suited for such microkernel environments without becoming unwieldy on monolithic environments.
EDI is apparently dead. The homepage is broken and shows me the source of the CGI script (proper doxygen here). It also has a hard dependency on posix threads.
CDI is ok for unix clones, but it needs some horrible hacks to use in an asynchronous message passing userspace to the extent that I decided against it. In comparison, UDI is fully suited for such microkernel environments without becoming unwieldy on monolithic environments.
EDI is apparently dead. The homepage is broken and shows me the source of the CGI script (proper doxygen here). It also has a hard dependency on posix threads.
- thepowersgang
- Member
- Posts: 734
- Joined: Tue Dec 25, 2007 6:03 am
- Libera.chat IRC: thePowersGang
- Location: Perth, Western Australia
- Contact:
Re: UDI, EDI, CDI Which do you use and why
I once had an attempt at an EDI shim, but never completed it (*goes and deletes that evil*). I may look into CDI sometime, either that or make a bigger set of UDI drivers (I have a NE2000 one that works well enough for my OS to use it).
IMO, the best is UDI, but it is complex. Hopefully the presence of multiple independent implementations will make it more likely to be used.
IMO, the best is UDI, but it is complex. Hopefully the presence of multiple independent implementations will make it more likely to be used.
Kernel Development, It's the brain surgery of programming.
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Acess2 OS (c) | Tifflin OS (rust) | mrustc - Rust compiler
Currently Working on: mrustc
Re: UDI, EDI, CDI Which do you use and why
What kind of hacks are you thinking of here? You won't easily get parallelism, but that's only a performance issue (and true when used with monolithic Unix-like kernels, too - changing that would involve API changes) and the basic implementation shouldn't involve any horribe hacks. Most of the OSes implementing CDI aren't exactly Unix clones, and a good share of them uses microkernels.Combuster wrote:CDI is ok for unix clones, but it needs some horrible hacks to use in an asynchronous message passing userspace to the extent that I decided against it.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: UDI, EDI, CDI Which do you use and why
What kind of hacks are you thinking of here?
The problem is that you have to block the thread for any calls made to services provided outside of the process. In a synchronous design you can just wait for the reply and then continue the code normally, but for an asynchronous design you'll have to deal with the problem of the next request arriving to your event queue (which you can't execute because it would interrupt running code) before the response of the pending operation you need for finishing the waiting request does.Driver code is never interrupted. The only exception is the function cdi_wait_irq: While it is running, IRQ handler may be executed.
Re: UDI, EDI, CDI Which do you use and why
I see. So you're getting the responses to your own requests in the same message queue as where you get new requests? Won't that always be awkward to work with as soon as one request needs to take a lock, no matter what the interface to the actual driver code looks like?
I can imagine that it's quite easy to write a simple network or block driver that doesn't need locking and can always accept new requests, but less so for something complex like a file system driver. So in the end I suppose you always end up moving requests from your message queue into a different queue where they wait for the lock to be released while you're waiting for the responses for your own requests.
Does UDI really work without such an internal queue? I don't know it well enough to say who'll call the callback when the driver is ready to process the next request and it may be hidden somewhere deep in the UDI mechanisms, but I'm pretty sure that it must be there.
I can imagine that it's quite easy to write a simple network or block driver that doesn't need locking and can always accept new requests, but less so for something complex like a file system driver. So in the end I suppose you always end up moving requests from your message queue into a different queue where they wait for the lock to be released while you're waiting for the responses for your own requests.
Does UDI really work without such an internal queue? I don't know it well enough to say who'll call the callback when the driver is ready to process the next request and it may be hidden somewhere deep in the UDI mechanisms, but I'm pretty sure that it must be there.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: UDI, EDI, CDI Which do you use and why
Even if you separate message queues, you have to know which one serve requests, and which ones serve replies. Besides, it might be very well the same process that delegates your permissions and relays the requests at the same time - will you suddenly force it to use a different channel for each possible message to keep them separate - that would be just as much an ugly hack, and a less favourable one than doublequeueing everything regardless of origin.I see. So you're getting the responses to your own requests in the same message queue as where you get new requests? Won't that always be awkward to work with as soon as one request needs to take a lock, no matter what the interface to the actual driver code looks like?
I consider locks an antipattern anyway - in particular the kind that don't get relinquished within a constant number of instructions. Locks add complexity and security hazards, can be nearly impossible to reason about, and they are often added to tasks that can be written intrinsically safe without them: proper queueing and threading give good multitasking without the use of any such constructs. There's no need at all to block app B from reading a cache because app A happens to be waiting for a disk access.
In fact, one such haphazard is that the specification implies that any cyclic attempt to communicate within CDI automatically deadlocks. Permanently, regardless of kernel architecture.
As far as your question is concerned: UDI strictly disallows blocking. It also provides queues as part of its own standard library for the obvious reason.
Re: UDI, EDI, CDI Which do you use and why
If you're interpreting "lock" as threads and their mutexes, then you're taking a much narrower definition than what I intended. What I mean is any mechanism that manages access to a shared resource by letting some users wait for others to release the resource. You may well implement this using queues, but the implemented concept remains the same.
At least as long as we don't introduce parallelism, CDI is neutral towards the way of implementing this. I would probably use a queue, too.
The important part is that you can use the same queuing in both frameworks. UDI just allows drivers having multiple requests being in a non-initial state (i.e. not waiting in the queue of incoming requests), whereas CDI doesn't.
At least as long as we don't introduce parallelism, CDI is neutral towards the way of implementing this. I would probably use a queue, too.
And I hope that nobody is suggesting this.Combuster wrote:There's no need at all to block app B from reading a cache because app A happens to be waiting for a disk access.
So far there hasn't been any need to do so. You don't have to agree with the approach, but the CDI way has always been to solve problems when they arise in practice.In fact, one such haphazard is that the specification implies that any cyclic attempt to communicate within CDI automatically deadlocks. Permanently, regardless of kernel architecture.
In my book, a request is still blocked when it's waiting in a queue, but that's terminology.As far as your question is concerned: UDI strictly disallows blocking. It also provides queues as part of its own standard library for the obvious reason.
The important part is that you can use the same queuing in both frameworks. UDI just allows drivers having multiple requests being in a non-initial state (i.e. not waiting in the queue of incoming requests), whereas CDI doesn't.
- gravaera
- Member
- Posts: 737
- Joined: Tue Jun 02, 2009 4:35 pm
- Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.
Re: UDI, EDI, CDI Which do you use and why
Yo:
--Peace out,
gravaera
There is no request queue as far as the UDI driver is concerned. The UDI driver uses callbacks and is not aware of the presence or absence of a request queue (and many environments may not use message loops, because their APIs are not asynchronous, or they are monolithic). The UDI driver has functions, and entry points.Kevin wrote:I see. So you're getting the responses to your own requests in the same message queue as where you get new requests?
There is no lock, and I am one of the people whose UDI environment is already completely lockless. UDI has no concept known as a "lock".Kevin wrote:Won't that always be awkward to work with as soon as one request needs to take a lock...
You don't need to wait for anything in an asynchronous design: that's the entire reason for asynchronous designKevin wrote:So in the end I suppose you always end up moving requests from your message queue into a different queue where they wait for the lock to be released while you're waiting for the responses for your own requests.
Yes, it will: the UDIRef reference implementation is mostly based on a monolithic blob design, and you can see this at work in there. My own environment is microkernel-like, and has separate-address-space drivers, and an almost purely asynchronous kernel, so I use request queues. This is just the most natural way for my kernel to do anything, being highly asynchronous.Kevin wrote:Does UDI really work without such an internal queue?
For a monolithic kernel, channel operations are transformed into function calls. Think of it as being the same as how the Linux kernel (and probably your own as well) silently optimizes locking primitives into "CLI/STI" on a single-CPU build.Kevin wrote:I don't know it well enough to say who'll call the callback when the driver is ready to process the next request and it may be hidden somewhere deep in the UDI mechanisms, but I'm pretty sure that it must be there.
No such concept exists in UDI, and it is entirely conceivable for a kernel to operate UDI drivers locklessly (like mine).Kevin wrote:If you're interpreting "lock" as threads and their mutexes, then you're taking a much narrower definition than what I intended. What I mean is any mechanism that manages access to a shared resource by letting some users wait for others to release the resource. You may well implement this using queues, but the implemented concept remains the same.
Requests don't block; they are queued and processed. Threads blockKevin wrote:In my book, a request is still blocked when it's waiting in a queue, but that's terminology.
--Peace out,
gravaera
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.
Re: UDI, EDI, CDI Which do you use and why
Hi gravaera,
you may prefer different terminology than what I use, but as I already explained to Combuster, in which I sense I meant them, I must assume that you're intentionally misunderstanding what I'm saying. Therefore I won't bother to reply to most of your points.
Also, maybe I should add that as a qemu block layer developer for a few years, I'm intimately familiar with different styles that coexist there, from synchronous requests and callback-style AIO to per-request coroutines and worker threads processing queues. So you can assume that I do know that callback-style APIs don't have an aio_lock() call - but semantically, queuing them is doing the same thing as a mutex: letting a request wait (and guess how qemu's coroutine locks are implemented internally? Right, queues.) It's all the same thing, just looking a bit different on the surface.
you may prefer different terminology than what I use, but as I already explained to Combuster, in which I sense I meant them, I must assume that you're intentionally misunderstanding what I'm saying. Therefore I won't bother to reply to most of your points.
Also, maybe I should add that as a qemu block layer developer for a few years, I'm intimately familiar with different styles that coexist there, from synchronous requests and callback-style AIO to per-request coroutines and worker threads processing queues. So you can assume that I do know that callback-style APIs don't have an aio_lock() call - but semantically, queuing them is doing the same thing as a mutex: letting a request wait (and guess how qemu's coroutine locks are implemented internally? Right, queues.) It's all the same thing, just looking a bit different on the surface.
We're talking specifically about Combuster's OS here (and in other quoted parts of my message that I won't reply to). There is no request queue as far as CDI is concerned either. It's the OS-specific implementation of the interfaces that needs to add it and that may or may not be easier with one interface or the other.gravaera wrote:There is no request queue as far as the UDI driver is concerned.Kevin wrote:I see. So you're getting the responses to your own requests in the same message queue as where you get new requests?
In something as complex as a file system driver, you will very likely have to let some requests wait on other requests. Yes, sitting in a queue is waiting, even if you avoid the bad word "lock". Changing terminology doesn't change the way your code works.You don't need to wait for anything in an asynchronous design: that's the entire reason for asynchronous design
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: UDI, EDI, CDI Which do you use and why
Considering thatKevin wrote:you may prefer different terminology than what I use
it might be wise to actually use the scientifically accepted definitions, instead of turning "lock" into something as meaningless as "anything that waits" which only ever serves the purpose of being unable to use the term.Wikipedia wrote:In computer science, a lock is a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution.
- gravaera
- Member
- Posts: 737
- Joined: Tue Jun 02, 2009 4:35 pm
- Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.
Re: UDI, EDI, CDI Which do you use and why
Yo:
Kevin, I didn't realize you were specifically talking about Combuster's environment, my bad;
--Peace out,
gravaera
Kevin, I didn't realize you were specifically talking about Combuster's environment, my bad;
--Peace out,
gravaera
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.