Re: Kernel thread scheduling
On 04/10/2015 09:09 AM, nick wrote:
On 2015-04-09 11:37 PM, Ruben Safir wrote:
On 04/09/2015 10:52 PM, nick wrote:
Before asking questions again like this please look into either using lxr or ctags to navigate the kernel tree for answers as can be faster then waiting for me or someone else to respond.
well, I reading the text is ctags aren't much value there.
Ctags is useful for searching the code, which is why I am recommending it. Nick
I have it built into gvim, but you can't use it from a textbook. I'm finding it is not as useful as it could be for the kernel code. There are stacks of tags to get around. Another 2 days to learn to get around tags in vi is not in the agenda right now. It is the tool I have so I'll have to live with it right now. I also have a question that is not obvious from the code I'm looking at. I'm not sure how these structs are attached together. Or more specifically, I'm not sure how pulling the correct sched_entity gets one the coresponding task_entity You have struct task_struct with a struct sched_entity struct sched_enitities are nodes in the RB tree which are a "container" for "struct rb_node run_node". So a look at sched_entity ... is in ../linux/sched.h 1161 struct sched_entity { 1162 struct load_weight load; /* for load-balancing */ 1163 struct rb_node run_node; 1164 struct list_head group_node; 1165 unsigned int on_rq; 1166 1167 u64 exec_start; 1168 u64 sum_exec_runtime; 1169 u64 vruntime; 1170 u64 prev_sum_exec_runtime; 1171 1172 u64 nr_migrations; 1173 1174 #ifdef CONFIG_SCHEDSTATS 1175 struct sched_statistics statistics; 1176 #endif 1177 1178 #ifdef CONFIG_FAIR_GROUP_SCHED 1179 int depth; 1180 struct sched_entity *parent; 1181 /* rq on which this entity is (to be) queued: */ 1182 struct cfs_rq *cfs_rq; 1183 /* rq "owned" by this entity/group: */ 1184 struct cfs_rq *my_q; 1185 #endif 1186 1187 #ifdef CONFIG_SMP 1188 /* Per-entity load-tracking */ 1189 struct sched_avg avg; 1190 #endif 1191 }; I see no means of referencing a specific task from this struct that forms the node. So when you pull the node with the smallest vruntime from the left most postion of the RB tree, by calling pick_next_task(), static struct sched_entity *__pick_next_entity(struct sched_entity *se) { struct rb_node *next = rb_next(&se->run_node); if (!next) return NULL; return rb_entry(next, struct sched_entity, run_node); } how do we know what task we are attached to? Ruben
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On 04/11/2015 10:21 PM, Ruben Safir wrote:
On 04/10/2015 09:09 AM, nick wrote:
On 2015-04-09 11:37 PM, Ruben Safir wrote:
On 04/09/2015 10:52 PM, nick wrote:
Before asking questions again like this please look into either using lxr or ctags to navigate the kernel tree for answers as can be faster then waiting for me or someone else to respond.
well, I reading the text is ctags aren't much value there.
Ctags is useful for searching the code, which is why I am recommending it. Nick
I have it built into gvim, but you can't use it from a textbook. I'm finding it is not as useful as it could be for the kernel code. There are stacks of tags to get around. Another 2 days to learn to get around tags in vi is not in the agenda right now. It is the tool I have so I'll have to live with it right now.
I also have a question that is not obvious from the code I'm looking at. I'm not sure how these structs are attached together. Or more specifically, I'm not sure how pulling the correct sched_entity gets one the coresponding task_entity
You have struct task_struct with a struct sched_entity
struct sched_enitities are nodes in the RB tree which are a "container" for "struct rb_node run_node".
So a look at sched_entity ... is in ../linux/sched.h
1161 struct sched_entity { 1162 struct load_weight load; /* for load-balancing */ 1163 struct rb_node run_node; 1164 struct list_head group_node; 1165 unsigned int on_rq; 1166 1167 u64 exec_start; 1168 u64 sum_exec_runtime; 1169 u64 vruntime; 1170 u64 prev_sum_exec_runtime; 1171 1172 u64 nr_migrations; 1173 1174 #ifdef CONFIG_SCHEDSTATS 1175 struct sched_statistics statistics; 1176 #endif 1177 1178 #ifdef CONFIG_FAIR_GROUP_SCHED 1179 int depth; 1180 struct sched_entity *parent; 1181 /* rq on which this entity is (to be) queued: */ 1182 struct cfs_rq *cfs_rq; 1183 /* rq "owned" by this entity/group: */ 1184 struct cfs_rq *my_q; 1185 #endif 1186 1187 #ifdef CONFIG_SMP 1188 /* Per-entity load-tracking */ 1189 struct sched_avg avg; 1190 #endif 1191 };
I see no means of referencing a specific task from this struct that forms the node. So when you pull the node with the smallest vruntime from the left most postion of the RB tree, by calling pick_next_task(),
static struct sched_entity *__pick_next_entity(struct sched_entity *se) { struct rb_node *next = rb_next(&se->run_node);
if (!next) return NULL;
return rb_entry(next, struct sched_entity, run_node); }
how do we know what task we are attached to?
Ruben
I'm still loss on how we know which taks_struct is being used but as a side note, I found this also very puzzling return rb_entry(next, struct sched_entity, run_node); With help I ran it down to this: http://lxr.free-electrons.com/source/include/linux/rbtree.h#L50 #define rb_entry(ptr, type, member) container_of(ptr, type, member) which leads me to yet another macro 798 #define container_of(ptr, type, member) ({ \ 799 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 800 (type *)( (char *)__mptr - offsetof(type,member) );}) This is a use of macros I'd never seen before up close. If anyone could help me understand it, I'd appreciate it. Ruben
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On 2015-04-11 11:02 PM, Ruben Safir wrote:
On 04/11/2015 10:21 PM, Ruben Safir wrote:
On 04/10/2015 09:09 AM, nick wrote:
On 2015-04-09 11:37 PM, Ruben Safir wrote:
On 04/09/2015 10:52 PM, nick wrote:
Before asking questions again like this please look into either using lxr or ctags to navigate the kernel tree for answers as can be faster then waiting for me or someone else to respond.
well, I reading the text is ctags aren't much value there.
Ctags is useful for searching the code, which is why I am recommending it. Nick
I have it built into gvim, but you can't use it from a textbook. I'm finding it is not as useful as it could be for the kernel code. There are stacks of tags to get around. Another 2 days to learn to get around tags in vi is not in the agenda right now. It is the tool I have so I'll have to live with it right now.
I also have a question that is not obvious from the code I'm looking at. I'm not sure how these structs are attached together. Or more specifically, I'm not sure how pulling the correct sched_entity gets one the coresponding task_entity
You have struct task_struct with a struct sched_entity
struct sched_enitities are nodes in the RB tree which are a "container" for "struct rb_node run_node".
So a look at sched_entity ... is in ../linux/sched.h
1161 struct sched_entity { 1162 struct load_weight load; /* for load-balancing */ 1163 struct rb_node run_node; 1164 struct list_head group_node; 1165 unsigned int on_rq; 1166 1167 u64 exec_start; 1168 u64 sum_exec_runtime; 1169 u64 vruntime; 1170 u64 prev_sum_exec_runtime; 1171 1172 u64 nr_migrations; 1173 1174 #ifdef CONFIG_SCHEDSTATS 1175 struct sched_statistics statistics; 1176 #endif 1177 1178 #ifdef CONFIG_FAIR_GROUP_SCHED 1179 int depth; 1180 struct sched_entity *parent; 1181 /* rq on which this entity is (to be) queued: */ 1182 struct cfs_rq *cfs_rq; 1183 /* rq "owned" by this entity/group: */ 1184 struct cfs_rq *my_q; 1185 #endif 1186 1187 #ifdef CONFIG_SMP 1188 /* Per-entity load-tracking */ 1189 struct sched_avg avg; 1190 #endif 1191 };
I see no means of referencing a specific task from this struct that forms the node. So when you pull the node with the smallest vruntime from the left most postion of the RB tree, by calling pick_next_task(),
static struct sched_entity *__pick_next_entity(struct sched_entity *se) { struct rb_node *next = rb_next(&se->run_node); This finds the next node in the red black tree for sched_enities. Basically rb_next finds the next node in the tree. The argument is the rb_node structure embedded in the structure using a red black tree.
if (!next) return NULL;
If there is no runnable task return NULL and pick_next_task will run the idle_task for this cpu.
return rb_entry(next, struct sched_entity, run_node); }
how do we know what task we are attached to?
Also try to read Chapter 6 of Linux Kernel Development as if have read that chapter understanding how red black trees and other data structures work in kernel code would make more sense. Nick
Ruben
I'm still loss on how we know which taks_struct is being used but as a side note, I found this also very puzzling
return rb_entry(next, struct sched_entity, run_node); With help I ran it down to this:
http://lxr.free-electrons.com/source/include/linux/rbtree.h#L50
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
which leads me to yet another macro
798 #define container_of(ptr, type, member) ({ \ 799 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 800 (type *)( (char *)__mptr - offsetof(type,member) );})
This is a use of macros I'd never seen before up close. If anyone could help me understand it, I'd appreciate it.
Ruben
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
_______________________________________________ Kernelnewbies mailing list Kernelnewbies@kernelnewbies.org http://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies
On 04/12/2015 12:16 AM, nick wrote:
This finds the next node in the red black tree for sched_enities. Basically rb_next finds the next node in the tree. The argument is the rb_node structure embedded in the structure using a red black tree.
The problem is this struct mystruc { int a; char * string; } wonderful; char * string2 = wonderful.string; There is no way to know that string2 comes from wonderful. That is the problem I have with the nodes The node is an instance of sched_entity. But unless there is a field that says what task_entity it is embedded in, in of itself, there is no way to know. There is no 'this' C. Obviously if does know. I'll look at chapter 6 I'm also looking at this static struct sched_entity *__pick_next_entity(struct sched_entity *se) { struct rb_node *next = rb_next(&se->run_node); if (!next) return NULL; return rb_entry(next, struct sched_entity, run_node); <<==macro } The macro is: I think: http://lxr.free-electrons.com/source/include/linux/rbtree.h#L50 50 #define rb_entry(ptr, type, member) container_of(ptr, type, member) container_of is http://lxr.free-electrons.com/source/include/linux/kernel.h#L798 791 /** 792 * container_of - cast a member of a structure out to the containing structure 793 * @ptr: the pointer to the member. 794 * @type: the type of the container struct this is embedded in. 795 * @member: the name of the member within the struct. 796 * 797 */ 798 #define container_of(ptr, type, member) ({ \ 799 const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 800 (type *)( (char *)__mptr - offsetof(type,member) );}) Now I have embedded macros which I thought you couldn't even do... In trying to understand this I stumbled on http://linuxkernel51.blogspot.com/2011/02/how-containerof-macro-works-exampl... How "container_of" macro works, & an Example Here iam giving a small code snippet that gives and idea about working of "container_of", this posed me little difficulty in understanding, after google-ing i got some examples and after working on that i wrote a simple C application that depicts its working. here i have defined two macros "offsetof" and "container_of" which i have extracted from "kernel.h" header. Please interpret this code and try some trick to understand "container_of". container_of macro is defined in linux/kernel.h syntax: container_of( pointer, container_type, container_field ); This macro takes a pointer to a filed name container_field, within a structure of type container_type, and returns a pointer to the containing structure . simply this is a convenience macro that may be used to obtain a pointer to a structure from a pointer to some other structure contained with in it. Code : #include <stdio.h> #include <stdlib.h> #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) struct test1 { int a; }; struct test2 { int b; struct test1 z; int c; }; int main() { /* existing structure */ struct test2 *obj; obj = malloc(sizeof(struct test2)); if(obj == NULL){ printf("Error: Memory not allocated...!\n"); } obj->z.a = 51; obj->b = 43; obj->c = 53; /* pointer to existing entry */ struct test1 *obj1 = &obj->z; //both of type test1 struct test2 *obj2 = container_of(obj1, struct test2, z); printf("obj2->b = %d\n", obj2->b); ///notsure what this does,need a nap return EXIT_SUCCESS; }
participants (2)
-
nick -
Ruben Safir