1: /******************************************************************************
2: * Include Files
3: * ***************************************************************************/
4: #include <stdio.h>
5: #include <stdlib.h>
6: #include <string.h>
7: /******************************************************************************
8: * Macros
9: * ***************************************************************************/
10: #define UINT_64 unsigned long long int
11: #define UCHAR unsigned char
12: #define OCTET 8
13: /******************************************************************************
14: * Global Variables
15: * ***************************************************************************/
16: /*
17: * Remaining Bits give information about empty bits left in one octet
18: */
19: static int remaining_bits = 8;
20: /*
21: * Global Index for Octet shifting
22: */
23: static int idx;
24: /*
25: * Offset for last set bit from LSB
26: */
27: static int offset = 0;
28: /******************************************************************************
29: * This function used to calculate offset length for given Decimal number
30: ******************************************************************************/
31: int find_offset(UINT_64 num)
32: {
33: int offset = 0;
34: UINT_64 mask = 1<<31;
35: while(mask)
36: {
37: if (num & mask)
38: {
39: return (32-offset);
40: }
41: offset++;
42: mask >>= 1;
43: }
44: return 0;
45: }
46: /*******************************************************************************
47: * This function used to fill bits into 2MB buffer
48: * ****************************************************************************/
49: void put_bits(UCHAR *buf, UINT_64 num)
50: {
51: int temp = 0;
52: /*
53: * Checking For OFFSET length
54: */
55: if ( offset < OCTET )
56: {
57: /*
58: * OFFSET Less than an OCTET means bit patter will fit into single index
59: */
60: if ( offset < remaining_bits )
61: {
62: remaining_bits -= offset;
63: *(buf + idx) |= num << remaining_bits;
64: } else {
65: /*
66: * This condition executes when bit patter is less than one octet
67: * but it entire octet is not available
68: */
69: *(buf + idx) |= num >> (offset - remaining_bits);
70: idx++;
71: temp = offset - remaining_bits;
72: *(buf + idx) |= num << (OCTET - temp);
73: remaining_bits = OCTET - temp;
74: }
75: return;
76: } else {
77: /*
78: * This condition executes when offset is larger than one octet
79: */
80: if ( remaining_bits < OCTET)
81: {
82: /*
83: * If last octet is not filled completely, this condition will
84: * execute
85: */
86: offset -= remaining_bits;
87: *(buf + idx) |= num >> offset;
88: idx++;
89: remaining_bits = OCTET;
90: if ( offset > 0)
91: {
92: /*
93: * If still offset is there, then start filling form begining
94: */
95: put_bits(buf,num);
96: }
97: } else {
98: /*
99: * This condition will execute when offset is larger than one octet
100: */
101: *(buf + idx) |= num >> (offset - OCTET);
102: idx++;
103: offset -= OCTET;
104: /*
105: * Continue with patter filling process if still offset is still
106: * there
107: */
108: put_bits(buf,num);
109: }
110: }
111: }
112: /******************************************************************************
113: * Main function
114: * ****************************************************************************/
115: main()
116: {
117: int i=0;
118: UINT_64 num = 0;
119: UCHAR *buff = NULL;
120: buff = (char *)malloc(2*1024*1024*sizeof(char));
121: if ( NULL == buff)
122: {
123: printf("failed to allocate memory\n");
124: exit(1);
125: }
126: memset(buff,0,2*1024*1024*sizeof(char));
127: do {
128: printf("\nEnter any Number or Zero to exit:");
129: scanf("%lld",&num);
130: /*
131: * Finding Last Enabled bit position from LSB
132: */
133: offset = find_offset(num);
134: /*
135: * Putting Bit patter into Buffer
136: */
137: put_bits(buff,num);
138: /*
139: * Display buffer status
140: */
141: for (i = 0; i <= idx; i++)
142: {
143: printf("%4X", buff[i]);
144: }
145: }while(num != 0);
146: printf("\n");
147: }
148: /******************************* End of File *********************************/
RTOS, Linux Kernel internal, OS-Programming C & Data Structures, Debugging, Optimizations, Makefiles and Wireless Technologies (Wi-Fi ,LTE and LTE-Advanced )
Search This Blog
Wednesday, December 3, 2014
Program for putting bits into buffer. This is useful in compression of data, avoide wastage of bits. This program will work for any 32-bits integers.
Tuesday, November 11, 2014
Write your own strcat function
1: int my_strcat(char *dst,char *src)
2: {
3: while(*dst != '\0')
4: dst++;
5: while(*src != '\0')
6: *dst++ = *src++;
7: *(dst+1) = '\0';
8: }
9: main()
10: {
11: char str1[100] = "hello";
12: char str2[100] = "world";
13: my_strcat(str1,str2);
14: printf("%s\n",str1);
15: }
Write your own strcmp function.
1: int my_strcmp(const char *str1,const char *str2)
2: {
3: while(1)
4: {
5: if ( *str1 != *str2)
6: return *str1 > *str2 ? 1:-1;
7: if(!*str1)
8: break;
9: str1++;
10: str2++;
11: }
12: return 0;
13: }
14: main()
15: {
16: char *str1 = "Hello";
17: char *str2 = "Hello";
18: printf("%d\n",my_strcmp(str1,str2));
19: }
Tree Insertion, Traversing , deletion and searching
1: /**************************
2: * Headers includes
3: ***************************/
4: #include <stdio.h>
5: #include <stdlib.h>
6: /**************************
7: * Structure for tree
8: ***************************/
9: typedef struct node_
10: {
11: struct node_ *right;
12: struct node_ *left;
13: int i;
14: }node_t;
15: /**************************
16: * Global tree root
17: ***************************/
18: node_t *root = NULL;
19: /**************************
20: * Preorder tree display
21: ***************************/
22: void preorder(node_t *node)
23: {
24: if ( node == NULL)
25: {
26: return;
27: }
28: printf("%d\t",node->i);
29: preorder(node->left);
30: preorder(node->right);
31: }
32: /**************************
33: * Inorder tree display
34: ***************************/
35: void inorder(node_t *node)
36: {
37: if ( node == NULL)
38: {
39: return;
40: }
41: inorder(node->left);
42: printf("%d\t",node->i);
43: inorder(node->right);
44: }
45: /**************************
46: * Postorder tree display
47: ***************************/
48: void postorder(node_t *node)
49: {
50: if ( node == NULL)
51: {
52: return;
53: }
54: postorder(node->left);
55: postorder(node->right);
56: printf("%d\t",node->i);
57: }
58: /**************************
59: * Options for tree traversing
60: ***************************/
61: void display_tree()
62: {
63: int choice = 0;
64: printf("1.Preorder\n2.Inorder\n3.Postorder\nEnter choice or 0:");
65: scanf("%d",&choice);
66: switch(choice)
67: {
68: case 1:
69: preorder(root);
70: break;
71: case 2:
72: inorder(root);
73: break;
74: case 3:
75: postorder(root);
76: break;
77: default:
78: printf("wrong Choice\n");
79: }
80: }
81: /**************************
82: * Function to Insert data into tree
83: ***************************/
84: node_t *add_node(node_t *node,int data)
85: {
86: if( NULL == node )
87: {
88: node_t *node = (node_t *) malloc(sizeof(node_t));
89: node->left = NULL;
90: node->right = NULL;
91: node->i = data;
92: if ( NULL == root )
93: {
94: root = node;
95: }
96: return node;
97: } else {
98: if ( data > node->i)
99: {
100: node->right = add_node(node->right,data);
101: } else if ( data < node->i)
102: {
103: node->left = add_node(node->left,data);
104: }
105: }
106: }
107: /**************************
108: * Option to Insert data
109: ***************************/
110: void make_tree()
111: {
112: int data = 0;
113: do {
114: printf("Enter Data or '0' to Exit:");
115: scanf("%d",&data);
116: if ( data != 0 )
117: {
118: add_node(root,data);
119: }
120: }while(data != 0);
121: }
122: /**************************
123: * Delete Tree nodes
124: ***************************/
125: node_t *delete_tree(node_t *node,int data)
126: {
127: static node_t *cur = NULL;
128: node_t *temp1 = NULL,*temp2 = NULL;
129: if ( NULL == root )
130: {
131: printf("Tree is empty\n");
132: return NULL;
133: }
134: if ( NULL == node)
135: {
136: printf("Data %d Not found for delete\n",data);
137: return root;
138: }
139: /**
140: * Deleting root node
141: */
142: if ( data == root->i)
143: {
144: /*
145: * No chiled in root
146: */
147: if ( NULL == root->left && NULL == root->right)
148: {
149: free(root);
150: root = NULL;
151: return NULL;
152: }
153: /*
154: * Only right chiled in root
155: */
156: if ( NULL == root->left && NULL != root->right)
157: {
158: temp1 = root;
159: root = root->right;
160: temp1->right = NULL;
161: free(temp1);
162: temp1 = NULL;
163: return root;
164: }
165: /*
166: * Only Left chiled in root
167: */
168: if ( NULL != root->left && NULL == root->right)
169: {
170: temp1 = root;
171: root = root->left;
172: temp1->left = NULL;
173: free(temp1);
174: temp1 = NULL;
175: return root;
176: }
177: /*
178: * Both left and right child present in root
179: */
180: if ( NULL != root->left && NULL != root->right )
181: {
182: temp2 = root;
183: temp1 = root->right;
184: while(temp1->left != NULL)
185: {
186: cur = temp1;
187: temp1 = temp1->left;
188: }
189: if ( NULL == cur)
190: {
191: temp1->left = temp2->left;
192: root = temp1;
193: temp2->left = temp2->right = NULL;
194: free(temp2);
195: temp2 = NULL;
196: return root;
197: } else {
198: cur->left = temp1->right;
199: temp1->left = temp2->left;
200: temp1->right = temp2->right;
201: root = temp1;
202: temp2->left = temp2->right = NULL;
203: free(temp2);
204: temp2 = NULL;
205: return root;
206: }
207: }
208: }
209: /**
210: * Deleting any data from tree except root
211: */
212: if ( data > node->i)
213: {
214: cur = node;
215: delete_tree(node->right,data);
216: } else if ( data < node->i )
217: {
218: cur = node;
219: delete_tree(node->left,data);
220: } else if ( data == node->i)
221: {
222: /*
223: * Data found now delete the node
224: */
225: if ( node->left == NULL && node->right == NULL && cur == node)
226: {
227: free(node);
228: node = NULL;
229: return NULL;
230: }
231: if ( cur->i < node->i)
232: {
233: temp1 = node->left;
234: if ( NULL != temp1)
235: {
236: cur->right = node->left;
237: while(temp1->right != NULL)
238: {
239: temp1 = temp1->right;
240: }
241: temp1->right = node->right;
242: } else {
243: cur->right = node->right;
244: }
245: }
246: if ( cur->i > node->i)
247: {
248: temp1 = node->right;
249: if ( NULL != temp1)
250: {
251: cur->left = node->right;
252: while(temp1->left != NULL)
253: {
254: temp1 = temp1->left;
255: }
256: temp1->left = node->left;
257: } else {
258: cur->left = node->left;
259: }
260: }
261: node->left = node->right = NULL;
262: free(node);
263: node = NULL;
264: }
265: return root;
266: }
267: /**************************
268: * Search function
269: ***************************/
270: node_t *search_tree(int data)
271: {
272: node_t *temp = root;
273: while(temp != NULL && temp->i != data )
274: {
275: temp = (data > temp->i) ? temp->right : temp->left;
276: }
277: if ( NULL == temp)
278: return NULL;
279: return temp;
280: }
281: /**************************
282: * Main function to display tree options
283: ***************************/
284: main()
285: {
286: int choice = 0,data = 0;
287: node_t *node = NULL;
288: do {
289: printf("\n************* Tree ************\n1.Add\n2.Display\n3.Delete\n4.Search\nEnter Your Choice or Zero to exit:");
290: scanf("%d",&choice);
291: switch(choice)
292: {
293: case 1:
294: make_tree();
295: break;
296: case 2:
297: display_tree();
298: break;
299: case 3:
300: printf("Enter Data to delete:");
301: scanf("%d",&data);
302: root = delete_tree(root,data);
303: break;
304: case 4:
305: printf("Enter Data to Search:");
306: scanf("%d",&data);
307: node = search_tree(data);
308: if ( NULL == node)
309: printf("Data Not fount\n");
310: else
311: printf("Data Found :: %d\n",node->i);
312: break;
313: default:
314: printf("Wrong Choice\n");
315: }
316: }while(choice != 0);
317: }
Sunday, October 5, 2014
WAP to display all set bit position in a given 32-bits number
1: main()
2: {
3: int i = 0x1234,pos = 1;
4: while(i)
5: {
6: if ( i & 0x01)
7: {
8: printf("%d\n",pos);
9: }
10: i = i>>1;
11: pos++;
12: }
13: }
WAP to shift all one's at one side in a given 32-bits number. i.e num = 0xcccccccc o/p - 0xffff0000
1: main()
2: {
3: unsigned int num = 0xcccccccc;
4: unsigned int res = 0,b1= 0,count=0;
5: printf("Num : 0x%x\n",num);
6: while(num)
7: {
8: if(num & 1)
9: {
10: b1 = (b1 << 1) | 1;
11: count++;
12: }
13: num >>= 1;
14: }
15: num = b1 << count;
16: printf("Result : 0x%x\n",num);
17: }
WAP to swap adjacent bits in a given 32-bits number
1: main()
2: {
3: int num;
4: printf("Enter No:");
5: scanf("%d",&num);
6: printf("rev = %d\n",(num>>1 & 0x55555555 | num<<1 & 0xaaaaaaaa));
7: }
WAP to find number of set bits in a given 32-bits number
1: main()
2: {
3: int num = 0x1fa12cde,count = 0;
4: while(num)
5: {
6: if(num & 1)
7: {
8: count++;
9: }
10: num = num >>1;
11: }
12: printf("Number of set bits = %d\n",count);
13: }
WAP to swap two nibbles in a given number
1: main()
2: {
3: unsigned int num = 0xfc;
4: num = (num>>4 & 0x0f) | (num<<4 & 0xf0);
5: printf("Result = 0x%x\n",num);
6: }
WAP to toggle all bits in a given 32-bits number
1: main()
2: {
3: unsigned int num = 0x4532fc1a; // Any 32-bits integer
4: unsigned int inv = i ^ 0xffffffff;
5: printf("inv = %x\n",inv);
6: }
WAP to overlap the bits from one number to another given number if the overlapping bit position is given
1: main()
2: {
3: int num1 = 0xffffffff;
4: int num2 = 0x12345678,c = 0;
5: int p1=0,p2=0;
6: int mask = 0;
7: // Enter the overlapping bits position
8: printf("Enter first overlapping bit position:");
9: scanf("%d",&p1);
10: printf("Enter second overlapping bit position:");
11: scanf("%d",&p2);
12: mask |= (1 << p1-1);
13: mask |= (1 << p2-1);
14: c = num2 & mask;
15: num1 |= c;
16: printf("After overlapping = %d\n",num1);
17: }
Saturday, October 4, 2014
WAP to toggle a bit at given position in given 32-bits number
1: main()
2: {
3: int num = 0xfcd78f11;
4: int pos = 10;
5: num = num ^ (1<< pos-1);
6: printf("res = %d\n",res);
7: }
WAP to increment a given number by one using bitwise operators
1: main()
2: {
3: int num = 0,res = 0;
4: printf("Enter number\n");
5: scanf("%d",&num);
6: res = ~num;
7: num ^= (num & ~-~num)| (~num & -~num);
8: printf("Inc Num : %d\n",num);
9: }
Sunday, September 21, 2014
WAP to detect loop in a singly linked list
1: void loop_detection()
2: {
3: list_t *slow = start;
4: list_t *fast = start;
5: while(slow != NULL && fast != NULL && fast->next != NULL)
6: {
7: slow = slow->next;
8: fast = fast->next->next;
9: if ( slow == fast)
10: {
11: printf("Loop detected\n");
12: return;
13: }
14: }
15: printf("No loop\n");
16: return;
17: }
Find middle node of given singly linked list
1: list_t * middle_node()
2: {
3: list_t *slow = start;
4: list_t *fast = start;
5: while(fast != NULL && fast->next != NULL)
6: {
7: slow = slow->next;
8: fast = fast->next->next;
9: }
10: printf("Middle Node is : %d\n",slow->data);
11: return slow;
12: }
WAP to find common data position in two different given Singly Linked lists.
1: void find_common_nodes_position(list_t *list1,list_t *list2)
2: {
3: int pos1=0,pos2=0;
4: list_t *temp1 = NULL;
5: list_t *temp2 = NULL;
6: for(pos1=1,temp1=list1;temp1;temp1=temp1->next,pos1++)
7: {
8: for(pos2=1,temp2 = list2;temp2;temp2 = temp2->next,pos2++)
9: {
10: if ( temp1->data == temp2->data)
11: {
12: printf("Data %d common at %d in list1 and %d at list2\n",
13: temp1->data,pos1,pos2);
14: }
15: }
16: }
17: return;
18: }
WAP to add all nodes value in a given SLL between the range from last i.e add all nodes form 2nd to 4th position from last.
1: int sum_of_nodes_from_last(int pos1,int pos2)
2: {
3: int sum = 0;
4: int i;
5: list_t *temp = NULL;
6: for(i=1,temp = start;temp;temp = temp->next,i++);
7: pos1 = i-pos1;
8: pos2 = i-pos2;
9: printf("i = %d\n",i);
10: for(i=1,temp = start;temp;temp = temp->next,i++)
11: {
12: if ( i >= pos2 && i <= pos1)
13: {
14: sum += temp->data;
15: }
16: }
17: return sum;
18: }
WAP to add all node value within a given range in SLL
1: int sum_of_nodes(int pos1,int pos2)
2: {
3: int sum = 0;
4: int i;
5: list_t *temp = NULL;
6: for(i=1,temp = start;temp;temp = temp->next,i++)
7: {
8: if ( i >= pos1 && i <= pos2)
9: {
10: sum += temp->data;
11: }
12: }
13: return sum;
14: }
WAP to find nth node from the last in a singly linked list
list_t *nth_node_from_last(int pos_from_last)
{
int len_of_ll = 0;
list_t *temp = NULL;
for(len_of_ll = 0,temp = start;temp;temp=temp->next,len_of_ll++);
// Length of LL is obtained
len_of_ll -= pos_from_last;
if ( len_of_ll <= 0)
{
printf("Position from last is out side the linked list range");
return NULL;
}
for(temp = start;len_of_ll;temp=temp->next,len_of_ll--);
return temp;
}
{
int len_of_ll = 0;
list_t *temp = NULL;
for(len_of_ll = 0,temp = start;temp;temp=temp->next,len_of_ll++);
// Length of LL is obtained
len_of_ll -= pos_from_last;
if ( len_of_ll <= 0)
{
printf("Position from last is out side the linked list range");
return NULL;
}
for(temp = start;len_of_ll;temp=temp->next,len_of_ll--);
return temp;
}
WAP to delete a node of singly linked list if only address on that node is given
1: void delete_node(list_t *node)
2: {
3: list_t *temp = node;
4: if (NULL == temp->next)
5: {
6: // Last node
7: free(temp);
8: return;
9: }
10: // Any node other than last
11: temp = temp->next;
12: node->data = temp->data;
13: node->next = temp->next;
14: free(temp);
15: return;
16: }
WAP to delete node in singly linked list when position and start pointer is given. Without using extra pointer
1: typedef struct list_
2: {
3: struct list_ *next;
4: int data;
5: }list_t;
6: void delete_list(int pos,list_t *node)
7: {
8: if ( NULL == node)
9: {
10: printf("Position not found\n");
11: return;
12: }
13: if ( pos == 1)
14: {
15: while ( node->next->next != NULL )
16: {
17: node->data = node->next->data;
18: node=node->next;
19: }
20: node->data = node->next->data;
21: free(node->next);
22: node->next = NULL;
23: return;
24: }
25: delete_list(--pos,node->next);
26: return;
27: }
28: main()
29: {
30: delete_list(pos,start);
31: }
WAP to reverse a singly linked list
1: typedef struct abc
2: {
3: int a;
4: struct abc *next;
5: }abc;
6: M-1 : Using three pointers
7: void revrse_list()
8: {
9: abc *temp = NULL,*temp1 = NULL, *temp2 = NULL;
10: temp = start;
11: temp1 = temp->next;
12: temp2 = temp1->next;
13: temp->next = NULL;
14: while(temp1->next != NULL)
15: {
16: temp = temp1;
17: temp1 = temp2;
18: temp2 = temp2->next;
19: temp1->next = temp;
20: }
21: start = temp1;
22: }
23: M-2 : Using recursive
24: abc *reverse_list(abc *node)
25: {
26: abc *temp = NULL;
27: if ( node->next == NULL)
28: {
29: start = node;
30: return node;
31: }
32: temp = reverse_list(node->next);
33: temp->next = node;
34: return node;
35: }
36: main()
37: {
38: abc *temp = NULL;
39: temp = reverse_list(start);
40: temp->next = NULL;
41: }
Wednesday, August 27, 2014
Behaviour of malloc() and free() functions
malloc() is vastly used in real time programing due to its contiguous allocation
of memory. So that fragmentation can be minimized.
But malloc() allocation itself causes sever of exception for programmer without showing significance error sometime.
1) Boundary of malloc()
int *ptr = (int *)malloc(sizeof(int)*10);
Above syntex of memory allocation represents that we are allocating 40 bytes of
contiguous memory to integer pointer ptr. as an result a size of 40 bytes chunk
is reserverd in heap to provide data read/write for pointer ptr.
A programmer can write data upto 40 byte of boundary legally. But
case 1: Legal writing
for(i = 0 ; i<10 ; i++)
{
ptr[i] = i;
}
This legal writing will not cause any error or fault. Allowed by compiler
case 2: Illegal writing
for(i = 0; i < 20 ; i++)
{
ptr[i] = i;
}
This writing is illegal. because it writes beyond the boundary of malloc.
But is still allowed by compiler.
2) Role of free() function in exceptional cases
Free function frees the memory allocated by the malloc() or calloc() or
realloc() functions. And makes it reusable for further memory allocation.
In above example free() functions play a different role
case 1: Legal writing
for(i = 0 ; i<10 ; i++)
{
ptr[i] = i;
}
free(ptr);
In this case free() will simply free the memory without any exception.
case 2: Illegal writing
for(i = 0; i<20 ; i++)
{
ptr[i] = i;
}
free(ptr);
In this example free() function will lead to an exception i.e SIGABRT. This
happens because free() function detects the extra byte has been written beyond
the boundry.
Observation : Here one thing is need to observe that using malloc() is a good
programing practice but in some of cases programmer probably does not notice on
the writing limit of malloc() and eventually ends with SIGABRT. If programmer
debugging the code they will cross check the memory allocation and double free()
scenario. It seems all right because code looks healthy. this kind of logical
issue resolved by examine writing limitation of malloc().
3) Does free() function really frees the memory
To better understand free() function once need to know how malloc() allocates
the memory. malloc() function passes the size of memory to allocate to the
system where kernel allocates required block for data. but kernel adds one
additional block of information before each allocation. That block called
meta-data and it contains mainly information about size of data that is
allocated free flag(0 = used, 1= free) and address of next meta-data.
Whenever free() functions tries to free a memory block it Enables the free
flag in meta-data structure. That means block of specific size is freed and
available for next time of allocation. Here the question is what happen next to
the data block can be easily understood by following examples.
case 1:
int *ptr = (int *)malloc(sizeof(int)*5);
int i = 0;
for(i = 0; i<5 ; i++)
{
ptr[i] = i;
}
for(i = 0; i<5 ; i++)
{
printf("%d\t",ptr[i]);
}
printf("\n");
free(ptr);
for(i = 0; i<5 ; i++)
{
printf("%d\t",ptr[i]);
}
Output -
0 1 2 3 4
0 0 2 3 4
[NOTE : This out may vary compiler wise]
free() function does not affect the data block. It simply makes it
available for next allocation.
This happens because of enabling free flag in meta-data. But what does it
really means enabling and disabling a flag. Whenever free() called to free a
dynamic memory it checks the meta data status and size of memory allocation.
Memory allocation happens by two mechanism in kernal space. if malloc is
allocating memory less then 135168 bytes ( approx figure, may vary), then it
uses sbrk() function to allocate memory. This allocated memory does not free
completely. programmer should assign NULL to the pointer after freeing it.
though this type of memory boundary is not well defined so sometime it is
observed that program can write beyond of allocation without showing any fault.
free happens only enabling the free flags in meta data.
But if memory to be allocated accedes 135168 bytes , system uses mmap() to
allocate memory. This kind of memory allocation very constrain to its boundary.
user can not write of use these memory after freeing it. because munmap is used
to free these memory.
To check memory allocation region by malloc we have one command in gdb.
(gdb) print or p malloc_stats(<address or pointer variable >)
output:
(gdb) p malloc_stats (0x7ffff7a9ea70)
Arena 0:
system bytes = 135168
in use bytes = 0
Total (incl. mmap):
system bytes = 135168
in use bytes = 0
max mmap regions = 0
max mmap bytes = 0
$2 = -136494720
(gdb)
Here we can see there are two regions defined in this out put 1. System Bytes
2. mmap regions
of memory. So that fragmentation can be minimized.
But malloc() allocation itself causes sever of exception for programmer without showing significance error sometime.
1) Boundary of malloc()
int *ptr = (int *)malloc(sizeof(int)*10);
Above syntex of memory allocation represents that we are allocating 40 bytes of
contiguous memory to integer pointer ptr. as an result a size of 40 bytes chunk
is reserverd in heap to provide data read/write for pointer ptr.
A programmer can write data upto 40 byte of boundary legally. But
case 1: Legal writing
for(i = 0 ; i<10 ; i++)
{
ptr[i] = i;
}
This legal writing will not cause any error or fault. Allowed by compiler
case 2: Illegal writing
for(i = 0; i < 20 ; i++)
{
ptr[i] = i;
}
This writing is illegal. because it writes beyond the boundary of malloc.
But is still allowed by compiler.
2) Role of free() function in exceptional cases
Free function frees the memory allocated by the malloc() or calloc() or
realloc() functions. And makes it reusable for further memory allocation.
In above example free() functions play a different role
case 1: Legal writing
for(i = 0 ; i<10 ; i++)
{
ptr[i] = i;
}
free(ptr);
In this case free() will simply free the memory without any exception.
case 2: Illegal writing
for(i = 0; i<20 ; i++)
{
ptr[i] = i;
}
free(ptr);
In this example free() function will lead to an exception i.e SIGABRT. This
happens because free() function detects the extra byte has been written beyond
the boundry.
Observation : Here one thing is need to observe that using malloc() is a good
programing practice but in some of cases programmer probably does not notice on
the writing limit of malloc() and eventually ends with SIGABRT. If programmer
debugging the code they will cross check the memory allocation and double free()
scenario. It seems all right because code looks healthy. this kind of logical
issue resolved by examine writing limitation of malloc().
3) Does free() function really frees the memory
To better understand free() function once need to know how malloc() allocates
the memory. malloc() function passes the size of memory to allocate to the
system where kernel allocates required block for data. but kernel adds one
additional block of information before each allocation. That block called
meta-data and it contains mainly information about size of data that is
allocated free flag(0 = used, 1= free) and address of next meta-data.
Whenever free() functions tries to free a memory block it Enables the free
flag in meta-data structure. That means block of specific size is freed and
available for next time of allocation. Here the question is what happen next to
the data block can be easily understood by following examples.
case 1:
int *ptr = (int *)malloc(sizeof(int)*5);
int i = 0;
for(i = 0; i<5 ; i++)
{
ptr[i] = i;
}
for(i = 0; i<5 ; i++)
{
printf("%d\t",ptr[i]);
}
printf("\n");
free(ptr);
for(i = 0; i<5 ; i++)
{
printf("%d\t",ptr[i]);
}
Output -
0 1 2 3 4
0 0 2 3 4
[NOTE : This out may vary compiler wise]
free() function does not affect the data block. It simply makes it
available for next allocation.
This happens because of enabling free flag in meta-data. But what does it
really means enabling and disabling a flag. Whenever free() called to free a
dynamic memory it checks the meta data status and size of memory allocation.
Memory allocation happens by two mechanism in kernal space. if malloc is
allocating memory less then 135168 bytes ( approx figure, may vary), then it
uses sbrk() function to allocate memory. This allocated memory does not free
completely. programmer should assign NULL to the pointer after freeing it.
though this type of memory boundary is not well defined so sometime it is
observed that program can write beyond of allocation without showing any fault.
free happens only enabling the free flags in meta data.
But if memory to be allocated accedes 135168 bytes , system uses mmap() to
allocate memory. This kind of memory allocation very constrain to its boundary.
user can not write of use these memory after freeing it. because munmap is used
to free these memory.
To check memory allocation region by malloc we have one command in gdb.
(gdb) print or p malloc_stats(<address or pointer variable >)
output:
(gdb) p malloc_stats (0x7ffff7a9ea70)
Arena 0:
system bytes = 135168
in use bytes = 0
Total (incl. mmap):
system bytes = 135168
in use bytes = 0
max mmap regions = 0
max mmap bytes = 0
$2 = -136494720
(gdb)
Here we can see there are two regions defined in this out put 1. System Bytes
2. mmap regions
Tuesday, April 22, 2014
Ellipses Operator (. . .)
This operator is used to represent various number of parameters involve. This is mainly used in function arguments , when the number of arguments is not known.
Ex -
int foo(int i, int j, . . .);
But we can use ellipses operator in other part of coding also.
In switch case
main()
{
--------
--------
switch(3)
{
case 1 ... 4:
printf("Option is between 1 to 4);
break;
Ex -
int foo(int i, int j, . . .);
But we can use ellipses operator in other part of coding also.
In switch case
main()
{
--------
--------
switch(3)
{
case 1 ... 4:
printf("Option is between 1 to 4);
break;
case 5 ... 9:
printf("Option is between 5 to 9);
break;
}
}
In array
Ellipses operator used in array initialization also. Using this operator we can partially initialize our arrays.
Ex -
main()
{
int arr[] = { [0 ... 4] 4, [5 ... 9] 5};
printf("arr[0] %d\n", arr[0]);
printf("arr[6] %d\n", arr[6]);
}
o/p -
arr[0] 4
arr[6] 5
Partially initialize the array
main()
{
int arr[10] = { [3]5, [1] = 4, [4] 3, [0] = 0 };
printf("arr[0] %d\n", arr[0]);
printf("arr[3] %d\n", arr[3]);
printf("arr[4] %d\n", arr[4]);
}
o/p -
arr[0] 0
arr[3] 5
arr[4] 3
Monday, April 21, 2014
Spin locks, Semaphore and Interrupt disabling Protection for kernel Control Paths
Kernel control paths accessing
the data structure UP protection MP further protection
Exceptions Semaphore None
Interrupts Local interrupt disabling Spin lock
Deferrable functions None None or
spin lock
Exceptions + Interrupts Local interrupt disabling Spin lock
Exceptions + Deferrable functions Local softirq disabling Spin lock
Interrupts + Deferrable functions Local interrupt disabling Spin lock
Exceptions + Interrupts +
Deferrable functions Local interrupt disabling Spin lock
UP - Uni-Processor, MP - Multiprocessor
Protecting Data Structure from Exception Handler
Protecting Data Structure from Interrupt Handler
Protecting Data Structure from Deferrable Functions
Source : Daniel P. Bovet & Marco Cesati Book
Sunday, April 20, 2014
Optimization Techniques that can improve your program performance
Program performance depends basically on two major areas one is memory and another is time. Programmer should aware of writing memory constrain and time constrain programs. Most of the optimization done at compilation level itself and some of the done at running time. Here we discuss on very small areas that really affecting our code performance.
Here i am sharing some of the techniques for beginners, which i learnt on my coding experience and reference taken from other sources. This optimizations techniques
Memory Optimization
Time optimization
Here i am sharing some of the techniques for beginners, which i learnt on my coding experience and reference taken from other sources. This optimizations techniques
Memory Optimization
- Memory allocation to your variables is a tactic. If memory has to be given to our array or string variables we follow static and dynamic memory allocation techniques.
- Static memory allocation has many issues , static memory allocate at compile time so we can not control the memory wastage if we were not used this memory efficiently. On the other hand life time of static memory depends on the program and function scope based on the memory allocation area. so before giving static memory to variables you should must have exact calculation of your requirements.
- Once memory has allocated statically it will occupy stack and other storage area till life time of program. This kind of memory occupancy will lead program in to huge memory wastage it can not provide memory reusability.
- Whereas Dynamic allocation allows program to allocate memory at run time and it can be freed after using it. Continually allocation of memory and not freeing them lead to code into memory overflow condition. so it is programmer should free dynamic pointers intelligently.
- Dynamic memory allocation where provides exact size of memory on the other hand it make cause memory leak type of serious issues.
- If it is memory allocation for structures or array of structures we should must go for dynamic memory allocation.
- If application sending any packets to network through sockets. they use one buffer to encode the packets into single body. Most of the programmer uses static memory buffers, if they use dynamic also they don't free after sending this on network, that should be freed.
- Be careful on choosing of data types for variables. i.e if variable range is between 0-255 then for this int32 or int64 data type is not required.
- Arrange variables in a certain orders like int, pointer, floating points and so forth. Because some of the compilers provide further level of optimization, it can improve code performance.
- Auto variables are stored in stack, if they are many then programmer has to move some of the auto variables in to different memory areas. by placing them in to global or using register storage class or if possible you can move them into heap.
- As much as try to avoid declaring any variable inside the loop. if it is not essential.
Code timing performance is totally depends on how the code is written
- Loop, nested loop they are major factors which causes delay in execution.
- Loop performance depends on the several parameters. Number of iteration, try to avoid infinite loops. Restrict the number of iteration, put exact condition for iteration.
- put constant calculation out side the loop.
- use bit-wise operator for certain type of arithmetic operation. ex- divided by two, multiplication of 2.
- Use look-up tables for trigonometric and logarithmic operations.
- try to avoid direct function calling within a loop use call-back functions instead.
- Make the loop blocking type. blocking loops improve the CPU performance.
- Always place data reading at the top of the loop and data writing at the end of the loop.
- Use inline functions that reduces function calling over head but increases size of code.
- use for, while and do while based on the compiler. because compiler decides the efficiency of loops.
- if else can be replaced by switch() if four or more than four items are there, then programmer can go for switch().
source: web and own experience
Saturday, April 19, 2014
Volatile keyword in C
Volatile is a type qualifier. It stop compiler to optimize certain area of code and prevent compiler to assume value of a variable hasn't changed. so compiler leave that segment code without optimized.
here is one example from #http://en.wikipedia.org/wiki/Volatile_variable
Without Volatile
Before compilation
Optimizing compiler observer that there is no other possible to change the value stored in foo. so compiler take the default value 0 and optimize the loop in to infinite .
After compilation
With Volatile
Here compiler will not assume any value and it will let the foo variable for the system to change the value.
Volatile is a type qualifier not a storage class so it does not change the area of storage
In kernel
Volatile is used in optimization barrier primitives. In Linux barrier() macro is used, which acts as an optimization barrier. barrier() macro defined as-
The volatile keyword disallow the compiler to reshuffle the asm instruction with the other instructions of the program.
Above example is taken from one of the kernel synchronization so called memory barrier.
Volatile keyword also allow access to memory mapped devices, allow usage of variable between set jump and long jump
here is one example from #http://en.wikipedia.org/wiki/Volatile_variable
Without Volatile
Before compilation
static int foo; void bar(void) { foo = 0; while (foo != 255) ; }
Optimizing compiler observer that there is no other possible to change the value stored in foo. so compiler take the default value 0 and optimize the loop in to infinite .
After compilation
void bar_optimized(void) { foo = 0; while (true) ; }
With Volatile
static volatile int foo; void bar (void) { foo = 0; while (foo != 255) ; }
Here compiler will not assume any value and it will let the foo variable for the system to change the value.
Volatile is a type qualifier not a storage class so it does not change the area of storage
In kernel
Volatile is used in optimization barrier primitives. In Linux barrier() macro is used, which acts as an optimization barrier. barrier() macro defined as-
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
The volatile keyword disallow the compiler to reshuffle the asm instruction with the other instructions of the program.
Above example is taken from one of the kernel synchronization so called memory barrier.
Volatile keyword also allow access to memory mapped devices, allow usage of variable between set jump and long jump
Why Virtual Memory ?
Whenever we run several processes simultaneously, they run successfully as long as physical memory addressing all the processes. sometime process size may exceed to the available physical memory limits , then the corresponding process is thrown out from the process queue, that should not happen in real.
Our physical memory is very limited and of course expensive. so Virtual provides that provision in which we can run multiple process at the same time with being worried about the physical memory size. virtual memory provides a logical layer between memory requested by the Process and Memory Management Unit(MMU). Virtual memory allows each process to use subset of available physical memory.
This all possible because of paging technique. Paging provides a memory translation between virtual address to physical address.
Our physical memory is very limited and of course expensive. so Virtual provides that provision in which we can run multiple process at the same time with being worried about the physical memory size. virtual memory provides a logical layer between memory requested by the Process and Memory Management Unit(MMU). Virtual memory allows each process to use subset of available physical memory.
This all possible because of paging technique. Paging provides a memory translation between virtual address to physical address.
Synchronization Techniques Used in kernel
Here are all the synchronization technique used by kernel programmers
- Per CPU Variable
- Atomic Operation
- Memory Barrier
- Spin Lock
- Semaphore
- Seqlocks
- Local Interrupt disabling
- Local Softirq disabling
- Read-Copy-Update (RCU)
Friday, April 18, 2014
What is dereferencing of a pointer?
Dereference operation means indirect operation. In pointers, pointer variable holds the address of similar kind of variable.
Ex- int *p;
'p' is a pointer to integer which holding the address of variable
int i=10;
when we want to retrieve value pointed by pointer variable 'p', We use *p to get the value so in this case we are not directly accessing the value of i, but we are indirectly accessing through pointer means dereferencing the pointer.
Ex- int *p;
'p' is a pointer to integer which holding the address of variable
int i=10;
when we want to retrieve value pointed by pointer variable 'p', We use *p to get the value so in this case we are not directly accessing the value of i, but we are indirectly accessing through pointer means dereferencing the pointer.
Thursday, April 17, 2014
THREAD PRIORITY
Priority Range in threads
0 to 63 consider as thread priority range. which is used by the system and users.
0- This is reserved for null threads for the idle mode.
1-23 - This range of priority used by kernel thread, user thread and servers.
24-32 - Used by kernel thread and system server. i.e server with portserv capability
32-63 - Reserved for real-time threads running on the kernel side.
Deadline Range
Deadline (ms) Thread Priority
>100 24 - 26
>20 27
2 - 20 28 - 31
0 to 63 consider as thread priority range. which is used by the system and users.
0- This is reserved for null threads for the idle mode.
1-23 - This range of priority used by kernel thread, user thread and servers.
24-32 - Used by kernel thread and system server. i.e server with portserv capability
32-63 - Reserved for real-time threads running on the kernel side.
Deadline Range
Deadline (ms) Thread Priority
>100 24 - 26
>20 27
2 - 20 28 - 31
KERNEL MEMORY ALLOCATOR (KMA) ALGORITHMS
1) Resource map allocator
2) Power-of-two free list
3) McKusick-Kernel allocator
4) Buddy System
5) Mach's zone allocator
6) Dynix Allocator
7) Solaris's Slab allocator
2) Power-of-two free list
3) McKusick-Kernel allocator
4) Buddy System
5) Mach's zone allocator
6) Dynix Allocator
7) Solaris's Slab allocator
Softirqs, Tasklets and Work Queue
Both are diferrable functions and they also called software interrupt. softirqs and tasklets are strictly correlated. tasklets are implemented on top of softirqs.
Softirqs are defined at compile time whereas tasklets are initialized and allocated at run time while loading the kernel module.
Softirqs are reentrant functions so it can run concurrently on the several CPUs. Spin loack techniques generally used to protect softirqs data structures. whereas tasklets run under restriction of kernel.
Tasklets schedule task for future purpose
Work Queue is similar to Tasklets, It also schedule task for future purpose. Both are use for the similar purposes, but tasklets are excute in interrupt context whereas work queue executes in process context.
Work queue allow kernel function to be activated and later executed by the kernel thread(worker thread).
Softirqs are defined at compile time whereas tasklets are initialized and allocated at run time while loading the kernel module.
Softirqs are reentrant functions so it can run concurrently on the several CPUs. Spin loack techniques generally used to protect softirqs data structures. whereas tasklets run under restriction of kernel.
Tasklets schedule task for future purpose
Work Queue is similar to Tasklets, It also schedule task for future purpose. Both are use for the similar purposes, but tasklets are excute in interrupt context whereas work queue executes in process context.
Work queue allow kernel function to be activated and later executed by the kernel thread(worker thread).
Wednesday, April 16, 2014
Deferrable Functions
Defferrable function is non-urgent interruptible kernel functions. Softirqs and Taskets are diferrable functions.
Subscribe to:
Posts (Atom)