Page 1 of 1

Task data

Posted: Sat Jul 09, 2011 2:10 am
by TylerH
Where could one keep a pointer the the task structure, so that it can be accessed (in ring 0) to identify the current task? Is there some "hidden" register or something that I could use?

Re: Task data

Posted: Sat Jul 09, 2011 2:12 am
by piranha
Well, you'd have to store each task's info in a structure or something, so just have a pointer in the kernel that gets updated to whatever the current task is on each schedule() call.

Like, struct task_data *current_task. And each time schedule is called, you just update the pointer.

-JL

Re: Task data

Posted: Sat Jul 09, 2011 7:13 am
by bluemoon
For my kernel, I store the process list in kernel heap, which is used by the scheduler and process creation/cleanup.
On the other hand, the process header (much like the idea of program segment prefix in DOS), which store per-process data like resource handles, are stored at fixed address on user space.

Re: Task data

Posted: Sat Jul 09, 2011 9:28 am
by Gigasoft
Where could one keep a pointer the the task structure, so that it can be accessed (in ring 0) to identify the current task? Is there some "hidden" register or something that I could use?
Often one has an entry in the GDT that points to variables that pertain to the CPU, including the current task pointer. This entry is then loaded into FS or GS at the start of every exception handler. Another method would be to have a global TLB mapping that points to these variables.

Here's something I came up with to easily access such variables from C++ (Visual Studio only), which might be found useful. It assumes that FS points to a a structure named ProcessorVars, and that it contains a field named Self, which points to the same structure. The macro CPUVar(fieldname) can then be used to refer to these fields. Although I'm sure this could probably be done better.

Code: Select all

class FSVar;
template<class T,class U> class StructVar {
public:
	DWORD ofs;
	StructVar(U T::*x) {ofs=(unsigned long)&(((T*)0)->*x);}
};
template<class T,class U,class V> class CustomVar;
template<class V,class T,class U>
inline CustomVar<T,U,V> GetCustomVar(U T::*x)
{
	return CustomVar<T,U,V>(x);
}
template<class T,class U> class CustomVar<T,U,FSVar> : StructVar<T,U> {
public:
	CustomVar<T,U,FSVar>(U T::*x) : StructVar<T,U>(x) {}
	operator const U() const {
		if(sizeof U==4) return (U)__readfsdword(ofs);
		if(sizeof U==2) return (U)__readfsword(ofs);
		if(sizeof U==1) return (U)__readfsbyte(ofs);
		U res;
		memcpy(&res,&CPUVar(Self),sizeof U);
		return res;
	}
	U operator=(U x)
	{
		if(sizeof U==4) __writefsdword(ofs,(DWORD)x);
		else if(sizeof U==2) __writefsword(ofs,(WORD)x);
		else if(sizeof U==1) __writefsbyte(ofs,(BYTE)x);
		else memcpy(&CPUVar(Self),&x,sizeof U);
		return U;
	}
	U operator->() const { return*this; }
};
#define CPUVar(x) GetCustomVar<FSVar>(&ProcessorVars::x)
(On second thought, I think this doesn't work as well as I originally intended. Not sure of what do to about fields of structures within the ProcessorVars structure, or arrays.)

Re: Task data

Posted: Sat Jul 09, 2011 2:46 pm
by bluemoon
Often one has an entry in the GDT that points to variables that pertain to the CPU
I have not think about MP yet (building UP kernel is already so complex for me)
But can we use paging to do this? A memory address region that is mapped differently on different CPU, which store the CPU identifier and per-CPU variables. And we setup the pages upon processors initialization in a logic similar to how we create process.

Re: Task data

Posted: Sun Jul 10, 2011 1:50 am
by egos
TylerH wrote:Where could one keep a pointer the the task structure, so that it can be accessed (in ring 0) to identify the current task? Is there some "hidden" register or something that I could use?
TSS.SP0. I have thread structure at the top of kernel stack for this thread. It's easy to use.