Is your OS self-hosting? Or is it one of your goals?

All off topic discussions go here. Everything from the funny thing your cat did to your favorite tv shows. Non-programming computer questions are ok too.
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Post by distantvoices »

pcmattman: I have looked randomly at the source of your os.

It's quite nice I say.

In your "gui_main.c" I've found what I consider a really nice & classic bug:

Code: Select all

RECT CreateRect( int x1, int y1, int x2, int y2 )
  196 {
  197 	RECT ret;
  198 	ret.x1 = x1;
  199 	ret.x2 = x2;
  200 	ret.y1 = y1;
  201 	ret.y2 = y2;
  202 
  203 	return ret;
  204 }
You allocate the RECT ret on the stack, thus it is a local varable, only visible inside of this function.

Then you return ret. This ain't work. YOu have to allocate place for the struct on the heap and return a pointer to ret to the calling function. The way you are doing it, you return a struct - which is located in an invalid place on the stack.

Maybe you got it working, but I'd rather allocate such stuff on the heap - and besides I can't imagine that this works. heap's way more secure.

If I'm in error, just tell. I'm always open to learning.

stay safe
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

distantvoices wrote:In your "gui_main.c" I've found what I consider a really nice & classic bug:
True, thanks for pointing that out. The GUI stuff is pretty obsolete now. That was back when I was still writing as a monolithic kernel. Since then I've switched to a microkernel design, so I'm going to be rewriting the GUI stuff in a different module.
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Post by distantvoices »

Ah, a fellow micro kernel designer. :-)

cool decision.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

distantvoices wrote:pcmattman: I have looked randomly at the source of your os.

It's quite nice I say.

In your "gui_main.c" I've found what I consider a really nice & classic bug:

Code: Select all

RECT CreateRect( int x1, int y1, int x2, int y2 )
  196 {
  197 	RECT ret;
  198 	ret.x1 = x1;
  199 	ret.x2 = x2;
  200 	ret.y1 = y1;
  201 	ret.y2 = y2;
  202 
  203 	return ret;
  204 }
You allocate the RECT ret on the stack, thus it is a local varable, only visible inside of this function.

Then you return ret. This ain't work. YOu have to allocate place for the struct on the heap and return a pointer to ret to the calling function. The way you are doing it, you return a struct - which is located in an invalid place on the stack.

Maybe you got it working, but I'd rather allocate such stuff on the heap - and besides I can't imagine that this works. heap's way more secure.

If I'm in error, just tell. I'm always open to learning.

stay safe
I may not be correct about this but I have always assumed that it will return a copy of the object. If he were to return a pointer to the ret object it would not work.
User avatar
os64dev
Member
Member
Posts: 553
Joined: Sat Jan 27, 2007 3:21 pm
Location: Best, Netherlands

Post by os64dev »

I may not be correct about this but I have always assumed that it will return a copy of the object. If he were to return a pointer to the ret object it would not work.
And where should the compiler put the copy of the object? It might work if you have something RECT x = CreateRect(0,0,100,100) and defined a copy constructor but that is an assumption. However in general i live to the rule: "assumption is the mother of all fuckups" and therefore use the heap.
Author of COBOS
frank
Member
Member
Posts: 729
Joined: Sat Dec 30, 2006 2:31 pm
Location: East Coast, USA

Post by frank »

os64dev wrote:
I may not be correct about this but I have always assumed that it will return a copy of the object. If he were to return a pointer to the ret object it would not work.
And where should the compiler put the copy of the object? It might work if you have something RECT x = CreateRect(0,0,100,100) and defined a copy constructor but that is an assumption. However in general i live to the rule: "assumption is the mother of all fuckups" and therefore use the heap.
Sorry I may be crazy but I am pretty sure that I read somewhere that if you are returning an object from a function it returns a copy of the object ie it keeps a copy on the stack and upon returning from the function is copies the object from the stack into the object you specify. (Obj o = Get_Obj( ); // o in this case )

If I am wrong about this then please someone correct me. I really would like to know the truth about it.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

frank wrote:
os64dev wrote:
I may not be correct about this but I have always assumed that it will return a copy of the object. If he were to return a pointer to the ret object it would not work.
And where should the compiler put the copy of the object? It might work if you have something RECT x = CreateRect(0,0,100,100) and defined a copy constructor but that is an assumption. However in general i live to the rule: "assumption is the mother of all fuckups" and therefore use the heap.
Sorry I may be crazy but I am pretty sure that I read somewhere that if you are returning an object from a function it returns a copy of the object ie it keeps a copy on the stack and upon returning from the function is copies the object from the stack into the object you specify. (Obj o = Get_Obj( ); // o in this case )

If I am wrong about this then please someone correct me. I really would like to know the truth about it.
<ignore>
Yes, but it does not actually return a object on the stack instead the l-value being assigned to by the function call is passed to the function as a pointer (on the stack).
</ignore>

<correction>
from the function is copies the object from the stack into the object you specify.
--- I just reread what you wrote. Yes. You are correct.
</correction>

Take for instance:

Code: Select all

struct sA{
	unsigned long a, b, c;
};

struct sA fA(struct sA a)
{
	++a.a;
	++a.b;
	++a.c;
	return a;
}

int main()
{
	struct sA a = {0, 0, 0};
	struct sA b;

	b = fA(a);
	return 1;
}
When looking at b = fA(a) you would think that the object would be placed on the stack then copied into b, but instead, even with no optimizations, a pointer to b is actually passed as the first argument to the function where the values are written using this pointer where return a is.

The same should happen with:

Code: Select all

sA fA(unsigned long a, unsigned long b, unsigned long c)
{
    sA ret;
    ret.a = a; ret.b = b; ret.c = c;
    return ret;
}
The sA ret is allocated on the stack (in the current frame), then assignments are made to this while lastly the first invisible argument to the function is a pointer to the actual instance of the variable you are using as a assignment. With optimization turned on I would imagine that it would eliminate the local variable ret, and just do a straight assignment to the return value (pointer to return value).

Code: Select all

08048344 <fA>:
 8048344:       55                      push   %ebp
 8048345:       89 e5                   mov    %esp,%ebp
 ///////////       pointer to return structure has been placed into edx.
 8048347:       8b 55 08                mov    0x8(%ebp),%edx
 ///////////       operations follow modifying the argument passed via stack. (copied onto the stack, rather)
 804834a:       8b 45 0c                mov    0xc(%ebp),%eax
 804834d:       40                      inc    %eax
 804834e:       89 45 0c                mov    %eax,0xc(%ebp)
 8048351:       8b 45 10                mov    0x10(%ebp),%eax
 8048354:       40                      inc    %eax
 8048355:       89 45 10                mov    %eax,0x10(%ebp)
 8048358:       8b 45 14                mov    0x14(%ebp),%eax
 804835b:       40                      inc    %eax
 804835c:       89 45 14                mov    %eax,0x14(%ebp)
 804835f:       8b 45 0c                mov    0xc(%ebp),%eax
 ///////////       edx is a pointer to the return value, here it copies.
 8048362:       89 02                   mov    %eax,(%edx)
 8048364:       8b 45 10                mov    0x10(%ebp),%eax
 8048367:       89 42 04                mov    %eax,0x4(%edx)
 804836a:       8b 45 14                mov    0x14(%ebp),%eax
 804836d:       89 42 08                mov    %eax,0x8(%edx)
 8048370:       89 d0                   mov    %edx,%eax
 8048372:       5d                      pop    %ebp
 ///////////       it is making the return value a pointer to where it placed the data, edx ==  eax.
 8048373:       c2 04 00                ret    $0x4

So it should be o-kay to return a function local variable or structure, but not a pointer to that local variable or structure since the pointer will reference a address on the stack that will be overwritten through stack manipulation very shortly or later on.
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Post by distantvoices »

First, sorry for calling something which is correct false. I have googled after franks comment and found some reference.

Albeit I prefer to allocate objects on the heap this doesn't permit the assumption that every other valid method is void.

I have simply forgotten that this is possible. Shame on me.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

distantvoices wrote:Ah, a fellow micro kernel designer. :-)

cool decision.
Only thing I can't figure out is how to let processes talk to drivers :D
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Post by distantvoices »

just send them messages.

User process wants something from service: send a message.
service wants something from driver: send a message.

As simple as that. ;-)

Messaging is the ipc-method of most importance in a microkernel environment. Messages transport the coordinates of system calls and calls amongst drivers & services & co. throu' the system.

More questions?
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

I am going to use messages, but it is still quite complex to figure out how to get return codes from calls, for instance.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

frank wrote:
os64dev wrote:
I may not be correct about this but I have always assumed that it will return a copy of the object. If he were to return a pointer to the ret object it would not work.
And where should the compiler put the copy of the object? It might work if you have something RECT x = CreateRect(0,0,100,100) and defined a copy constructor but that is an assumption. However in general i live to the rule: "assumption is the mother of all fuckups" and therefore use the heap.
Sorry I may be crazy but I am pretty sure that I read somewhere that if you are returning an object from a function it returns a copy of the object ie it keeps a copy on the stack and upon returning from the function is copies the object from the stack into the object you specify. (Obj o = Get_Obj( ); // o in this case )

If I am wrong about this then please someone correct me. I really would like to know the truth about it.
It does work.

Theoretical way to get it working right:
You create a local variable with that name, reserve space on the stack for a temporary of the same type, call the function with a reference to the location of the temporary. The function creates its own local variable, initializes it, calls an assignment constructor to the temporary, destructs its own copy, returns. The original function runs an assignment constructor to its own object and destructs the temporary.

The practical way:
You allocate (but do not create) a local variable of the same name and pass a reference to it. The function creates its new object in the place of the reference. It then "returns" this reference, you use it.

If this didn't work, most of C++ would not work. Iterators are intended to be copied all the time and are supposed to be used like this.

It's called Return Value Optimization by the way, which is invented in order to make these kind of huge return values work efficiently. If you have a stack of functions each returning an object it should just allocate one of them and keep telling the next function where to put the object (potentially with tail recursion optimizations!)
distantvoices
Member
Member
Posts: 1600
Joined: Wed Oct 18, 2006 11:59 am
Location: Vienna/Austria
Contact:

Post by distantvoices »

@pcmattman:

It's the following situation, ain't it?

caller issues a system call x()

x(), in it's inner workings, does quite some checking and preprocessing if applicable and then fills in some standard message (f. ex. with the loco to send the message to) and calls send(&message) -> after that, the caller should receive(&message) from callee.

then, the callee fetches the message from said loco, processes it. it can (and mostatimes will) put the return code regarding that processing into a message and sends it to the caller. back to receive(&message).

the caller - the function x() pries the return code from the retrieved message (a field in the message to pry the code from should be known by both the caller and the callee per convention)

There are some tricky situations arising, especially if you intend to use paging and process address spaces - how to transfer data from process A to process B (I pipe it throu the kernel-a nasty and expensive operation or use shared memory segments - quite nifty and niiiiice).

stay safe :-)
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

There are some tricky situations arising, especially if you intend to use paging and process address spaces - how to transfer data from process A to process B (I pipe it throu the kernel-a nasty and expensive operation or use shared memory segments - quite nifty and niiiiice).
Just got paging working with multiple processes last night - now I have to figure out how to do messaging.

Until a better implementation is figured out I'll probably store messages in linked lists on the kernel heap.
Post Reply