If below questions seem alien, think again if you are ready!!
So many ways:
unsigned int x=1;
#include "stdio.h"
main()
{
int a=10;
int b=10;
char *aa=&a;
int *ptr1=malloc(10);
int cpid=fork();
int *ptr2=malloc(20);
int *ptr3=malloc(30);
if(cpid==0)
{
printf("\tcpid0 a:%d b:%d\n", a, b);
a++; b++;
sleep(1);
printf("\tcpid0 a:%d b:%d\n", a, b);
printf("\tcpid0 PTR %p %p %p\n", ptr1, ptr2, ptr3);
*ptr1=100;
*ptr2=200;
*ptr3=300;
printf("\tcpid0 PTRVAL %d %d %d\n", *ptr1, *ptr2, *ptr3);
sleep(3);
printf("\tcpid0 PTRVAL %d %d %d\n", *ptr1, *ptr2, *ptr3);
}
else
{
printf("cpid non0: a:%d b:%d\n", a, b);
a+=2;
b+=2;
sleep(1);
printf("cpid non0: a:%d b:%d\n", a, b);
*ptr1=10;
*ptr2=20;
*ptr3=30;
printf("cpid non0 PTR :%p %p %p\n", ptr1, ptr2, ptr3);
printf("cpid non0 PTRVAL:%d %d %d\n", *ptr1, *ptr2, *ptr3);
sleep(5);
printf("cpid non0 PTRVAL:%d %d %d\n", *ptr1, *ptr2, *ptr3);
}
}
Output
cpid non0: a:10 b:10
cpid0 a:10 b:10
cpid non0: a:12 b:12
cpid non0 PTR :0x2393010 0x2393030 0x2393050
cpid non0 PTRVAL:10 20 30
cpid0 a:11 b:11
cpid0 PTR 0x2393010 0x2393030 0x2393050
cpid0 PTRVAL 100 200 300
cpid0 PTRVAL 100 200 300
cpid non0 PTRVAL:10 20 30
main()
{ static int i; for(i=0;i;i--) main() }
Output: Seg Fault. i=0 is assignment not initialization. Every time i is 5.
Does it Fix? { static int i=5; for(i;i;i--) main() } NO.
2.
char *getstring1() { char str[]="Alas! I cant be printed"; return str; }
char *getstring2() { char *str="Hurray!! I shall be shown"; return str;}
main(){ printf("str1: %s, str2:%s\n", getstring1(), getstring2()); }
Output: str1: b@, str2:Hurray!! I shall be shown
3.
struct s{char c[0];}; sizeof(struct s) : 0
4.
register int i=10; int *ptr=&i; //error: address of register variable requested
5.
void *void_ptr, v; v=0; //error: variable or field 'v' declared void
void_ptr=&v; printf("%v", *vptr); //error: invalid use of void expression
6. Fix this as it does not actually swap strings
swap(char *str1, char *str2){ char*tmp=str1; str1=str2; str2=tmp; }
main(){ char s1[]="Hi", s2[]="Hello"; swap(s1, s2); }
Fix: ??
7. Modulus operator follows numerator sign
3%-8 = 3
-3%-8 = -3
-3%8 = -3
3%-8/2 = 3/2=1
8.
int i=10; static int j=i; //error: initializer element is not constant
9. float a; (int)a=20; / / error: lvalue required as left operand of assignment
10. error: macro names must be identifier
#ifdef 1
int some=10;
#endif
11. valid. some=0.
#define M 0 //or any value 1, or any string "hi"
#ifdef M
int some=0;
#else
#int some=1;
#endif
12. Replace #ifdef with #if
Result different. M=0 -> some=1; M=10 -> some=0; M="hi" -> error: token ""hi"" is not valid in preprocessor expressions
13.
Case expression can not be string, switch condition can be string.
e.g. switch( *(1+"AB""CD"+1)) //2+"ABCD" = "ABCD"[2] = 'C' //legal.
Case expression is int. If float given in case expression, it is type casted to int.
1.
switch(0x0)
{ case NULL: case 0: case '\0': } //error: duplicate case not allowed.
int i=0;
2.
switch(i)
{
case 1: int j=10; break;
case 2: int j=10; break;
}
switch.c:9: error: a label can only be part of a statement and a declaration is not a statement
switch.c:10: error: a label can only be part of a statement and a declaration is not a statement
switch.c:10: error: redefinition of 'j'
switch.c:9: note: previous definition of 'j' was here
3.
int i=0;
switch(i)
{
case 1: int j=10; break;
case 2: j=10; break;
}
//error: a label can only be part of a statement and a declaration is not a statement
move data to new pointer and free old pointer, return new pointer, OR
keep old pointer, extend it by given size and return old pointer.
Newly allocated memory is uninitialized, realloc(NULL, 10) is safe
write() is faster for writing data to file compared to printf, fprintf, as parsing is required before calling low level write function.
memcpy() is faster than strcpy() as it does not have to check each byte for NULL.
const char *ptr="Hello"; ptr="Cielo"; (OK) ptr[0]='a';(ERR, ptr is pointer to const char)
Some blogs I really like to follow:
http://embeddedgurus.com/barr-code/
Determine if stack grows up/down (low to high / high to low memory)?
int* f1() { char c; return &c; }
int* f2() { char c; return &c; }
main()
{ int *a1=f1(); int *a2=f2(); /*Get diff of a1 and s2 to determine*/ }
Obviously above does not work, you get both values b3375000 b3375000. Heard of virtual memory? Same address re-used
You need to call function from function to actually get stack direction.
int does_stack_grow_to_high_mem()
{
char c1; //f1b33727
int *p=f1(); //f1b3370f
if(c1>p) return 1;
else return 0;
else return 0;
}
How to do it in single function?
void does_stack_grow_to_high_mem(int *ptr) {
int i;
if (!ptr) does_stack_grow_to_high_mem(&i);
else if (ptr < &i) return 1; //yes to high memory
else return 0;
}
does_stack_grow_to_high_mem(NULL);
Determine how much stack size a function uses?
This can be read in output of assembler.
main() { int i=10; printf("%d", i); }
# gcc -S prog.c
# vi prog.s -> Look for subq. In this case 16 Bytes are taken.
main:
.LFB0:
...
.cfi_def_cfa_register 6
subq $16, %rsp
main() { int i=10; int j[1024]; printf("%d", i); }
main:
.LFB0:
subq $4112, %rsp //Increased by 1024*4=4096
main() { int i=10; int j[1024]={0}; printf("%d", i); }
main:
.LFB0:
...
pushq %rbx
subq $4120, %rsp //Increased by 8 Bytes when it is initialized
main() { int i=10; }
You shall see no stack [subq] is used in .s file as compiler optimized unused variable i.
Find machine is little or big endian?
So many ways:
unsigned int x=1;
printf "%d", (int) ( ( (char*) &x) [0] ));
isBE()
union {
unsigned int i;
char c[4];
} endian = { 0x01000000 };
return endian.c[0];
int x=1;
if(*(char*)&x)==1) LE
- Define a macro for milli-seconds in a day.
- Declare an array size 64K: #define SIZE (1<<16)
- Swap two numbers,
void
swap(
int
*ptrx,
int
*ptry)
//smartness case if(ptrx==ptry) return; //For case e.g. quick sort when var is swapped with self
Which variable goes in stack/BSS/ReadOnlyData Segment?
#include "stdio.h"
static
int g_static_x; //BSS
static
int g_static_x_init=0xCAFECAFE; //DATA
static
int g_static_x_init0=0; //BSS
const
int g_const_x; //BSS
//Can be modified via ptr
const
int g_const_x_init=0xDEADBEEF;
//ReadOnly Data //crash if modified via ptr
const
int g_const_x_init0=0;
//ReadOnly Data //crash if modified via ptr
int
g_x; //BSS
int
g_x_init=0xDEADBEAD; //BSS
int
g_x_init0=0; //BSS
main()
{
printf("Global : g_static_x [@%p]=0x%x\n", &g_static_x,
g_static_x );
printf("Global : g_static_x_init [@%p]=0x%x\n", &g_static_x_init,
g_static_x_init);
printf("Global : g_static_x_init0 [@%p]=0x%x\n\n",
&g_static_x_init0, g_static_x_init0);
printf("Global const : g_const_x [@%p]=0x%x\n", &g_const_x,
g_const_x);
printf("Global const :
g_const_x_init [@%p]=0x%x\n",
&g_const_x_init, g_const_x_init);
printf("Global const :
g_const_x_init0 [@%p]=0x%x\n\n\n",
&g_const_x_init0, g_const_x_init0);
static int l_static_x; //BSS
static int l_static_x_init=0xDEADCAFE;//BSS
static int l_static_x_init0=0; //Data
const int l_const_x; //Stack //Can be modified via
ptr
const int l_const_x_init=0xBEEFBEEF; //Stack //Can be modified via ptr
const int l_const_x_init0=0; //Stack //Can be modified via ptr
printf("Local : l_static_x [@%p]=0x%x\n", &l_static_x,
l_static_x );
printf("Local : l_static_x_init [@%p]=0x%x\n", &l_static_x_init,
l_static_x_init);
printf("Local : l_static_x_init0
[@%p]=0x%x\n\n", &l_static_x_init0, l_static_x_init0);
printf("Local const : l_const_x [@%p]=0x%x\n", &l_const_x,
l_const_x);
printf("Local const : l_const_x_init [@%p]=0x%x\n", &l_const_x_init,
l_const_x_init);
printf("Local const : l_const_x_init0 [@%p]=0x%x\n\n\n",
&l_const_x_init0, l_const_x_init0);
char str[]="i-techh"; //Stack
char *p_str="i-techh"; //Stack
static char
static_str[]="i-techh";
//Data
static char
*static_p_str="i-techh";
//pointing to address in text segment
printf("Local : str[] [@%p]=%s\n", &str[0],
str );
printf("Local : p_str [@%p]=%s\n", &p_str,
p_str);
printf("Local : static_str[] [@%p]=%s\n", &static_str[0],
static_str);
printf("Local const : static_p_str [@%p]=%s\n\n", &static_p_str,
static_p_str);
}
/*
Global : g_static_x [@0x600d8c]=0x0
Global : g_static_x_init [@0x600d58]=0xcafecafe
Global : g_static_x_init0 [@0x600d90]=0x0
Global
const : g_const_x [@0x600da0]=0x0
Global
const : g_const_x_init
[@0x4007b8]=0xdeadbeef
Global
const : g_const_x_init0 [@0x4007bc]=0x0
Local : l_static_x [@0x600d94]=0x0
Local : l_static_x_init [@0x600d60]=0xdeadcafe
Local : l_static_x_init0 [@0x600d98]=0x0
Local
const : l_const_x [@0x7fff29b8bbbc]=0x0
Local
const : l_const_x_init [@0x7fff29b8bbb8]=0xbeefbeef
Local
const : l_const_x_init0 [@0x7fff29b8bbb4]=0x0
Local : str[] [@0x7fff29b8bba0]=i-techh
Local : p_str [@0x7fff29b8bb98]=i-techh
Local : static_str[] [@0x600d64]=i-techh
Local
const : static_p_str [@0x600d70]=i-techh
*/
This
can be checked using objdump -t a.out
SYMBOL
TABLE:
0000000000000000
l df *ABS* 0000000000000000 which_var_goes_where.c
0000000000600d8c
l O .bss 0000000000000004 g_static_x
0000000000600d58
l O .data 0000000000000004 g_static_x_init
0000000000600d90
l O .bss 0000000000000004 g_static_x_init0
0000000000600d94
l O .bss 0000000000000004 l_static_x.2059
0000000000600d60
l O .data 0000000000000004 l_static_x_init.2060
0000000000600d98
l O .bss 0000000000000004 l_static_x_init0.2061
0000000000600d64
l O .data 0000000000000008 static_str.2067
0000000000600d70
l O .data 0000000000000008 static_p_str.2068
0000000000600d5c
g O .data 0000000000000004 g_x_init
0000000000600d9c
g O .bss 0000000000000004 g_x
0000000000600d88
g O .bss 0000000000000004 g_x_init0
00000000004007b8
g O .rodata 0000000000000004 g_const_x_init
0000000000600da0
g O .bss 0000000000000004 g_const_x
00000000004004c4
g F .text 00000000000001f8 main
0000000000400390
g F .init 0000000000000000 _init
*
static local variables have .number added and have address outside stack space.
*
Other local variables are not seen in symbol table e.g. l_const_x, str[],
p_str[] etc
Following
actions generate compilation error: assignment of read-only variable:
/*
g_const_x=0; g_const_x_init=0x10; g_const_x_init0=0
l_const_x=0; l_const_x_init=0x10l l_const_x_init0=10
*/
Extending
this problem further to understand what const variables can be modified using
pointer, but generates warning: assignment discards qualifiers from the pointer
type
int
*p;
p=&g_const_x; *p=10;
//does not seg fault
p=&l_const_x; *p=10;
//does not seg fault
p=&l_const_x_init0; *p=10; //does not seg fault
Below generate warning as well as seg faults.
p=&g_const_x_init0; *p=10; //seg fault
p=&g_const_x_init; *p=10; //seg fault
p=&l_const_x_init; *p=10; //seg fault
Fork Concepts: Find output of below commands on GCC
#include "stdio.h"
main()
{
int a=10;
int b=10;
char *aa=&a;
int *ptr1=malloc(10);
int cpid=fork();
int *ptr2=malloc(20);
int *ptr3=malloc(30);
if(cpid==0)
{
printf("\tcpid0 a:%d b:%d\n", a, b);
a++; b++;
sleep(1);
printf("\tcpid0 a:%d b:%d\n", a, b);
printf("\tcpid0 PTR %p %p %p\n", ptr1, ptr2, ptr3);
*ptr1=100;
*ptr2=200;
*ptr3=300;
printf("\tcpid0 PTRVAL %d %d %d\n", *ptr1, *ptr2, *ptr3);
sleep(3);
printf("\tcpid0 PTRVAL %d %d %d\n", *ptr1, *ptr2, *ptr3);
}
else
{
printf("cpid non0: a:%d b:%d\n", a, b);
a+=2;
b+=2;
sleep(1);
printf("cpid non0: a:%d b:%d\n", a, b);
*ptr1=10;
*ptr2=20;
*ptr3=30;
printf("cpid non0 PTR :%p %p %p\n", ptr1, ptr2, ptr3);
printf("cpid non0 PTRVAL:%d %d %d\n", *ptr1, *ptr2, *ptr3);
sleep(5);
printf("cpid non0 PTRVAL:%d %d %d\n", *ptr1, *ptr2, *ptr3);
}
}
Output
cpid non0: a:10 b:10
cpid0 a:10 b:10
cpid non0: a:12 b:12
cpid non0 PTR :0x2393010 0x2393030 0x2393050
cpid non0 PTRVAL:10 20 30
cpid0 a:11 b:11
cpid0 PTR 0x2393010 0x2393030 0x2393050
cpid0 PTRVAL 100 200 300
cpid0 PTRVAL 100 200 300
cpid non0 PTRVAL:10 20 30
Spot Errors: C Tricks
1.main()
{ static int i; for(i=0;i;i--) main() }
Output: Seg Fault. i=0 is assignment not initialization. Every time i is 5.
Does it Fix? { static int i=5; for(i;i;i--) main() } NO.
2.
char *getstring1() { char str[]="Alas! I cant be printed"; return str; }
char *getstring2() { char *str="Hurray!! I shall be shown"; return str;}
main(){ printf("str1: %s, str2:%s\n", getstring1(), getstring2()); }
Output: str1: b@, str2:Hurray!! I shall be shown
struct s{char c[0];}; sizeof(struct s) : 0
4.
register int i=10; int *ptr=&i; //error: address of register variable requested
5.
void *void_ptr, v; v=0; //error: variable or field 'v' declared void
void_ptr=&v; printf("%v", *vptr); //error: invalid use of void expression
6. Fix this as it does not actually swap strings
swap(char *str1, char *str2){ char*tmp=str1; str1=str2; str2=tmp; }
main(){ char s1[]="Hi", s2[]="Hello"; swap(s1, s2); }
Fix: ??
7. Modulus operator follows numerator sign
3%-8 = 3
-3%-8 = -3
-3%8 = -3
3%-8/2 = 3/2=1
8.
int i=10; static int j=i; //error: initializer element is not constant
9. float a; (int)a=20; / / error: lvalue required as left operand of assignment
10. error: macro names must be identifier
#ifdef 1
int some=10;
#endif
11. valid. some=0.
#define M 0 //or any value 1, or any string "hi"
#ifdef M
int some=0;
#else
#int some=1;
#endif
12. Replace #ifdef with #if
Result different. M=0 -> some=1; M=10 -> some=0; M="hi" -> error: token ""hi"" is not valid in preprocessor expressions
13.
Spot Errors: switch-case tricks
Compiler implements jump table for cases in switch.Case expression can not be string, switch condition can be string.
e.g. switch( *(1+"AB""CD"+1)) //2+"ABCD" = "ABCD"[2] = 'C' //legal.
Case expression is int. If float given in case expression, it is type casted to int.
1.
switch(0x0)
{ case NULL: case 0: case '\0': } //error: duplicate case not allowed.
int i=0;
2.
switch(i)
{
case 1: int j=10; break;
case 2: int j=10; break;
}
switch.c:9: error: a label can only be part of a statement and a declaration is not a statement
switch.c:10: error: a label can only be part of a statement and a declaration is not a statement
switch.c:10: error: redefinition of 'j'
switch.c:9: note: previous definition of 'j' was here
3.
int i=0;
switch(i)
{
case 1: int j=10; break;
case 2: j=10; break;
}
//error: a label can only be part of a statement and a declaration is not a statement
4. Will there be any jump for switch in below code assembly?
int i=0;
switch(i)
{
case 1: break;
case 2: break;
}
Ans: NO.
5. Objdump for below code:
int i=0, j;
switch(i)
{
case 1: j=10; break;
case 2: j=20; break;
}
0000000000400474:
400474: 55 push %rbp
400475: 48 89 e5 mov %rsp,%rbp
400478: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
40047f: 8b 45 f8 mov -0x8(%rbp),%eax
400482: 83 f8 01 cmp $0x1,%eax
400485: 74 07 je 40048e
400487: 83 f8 02 cmp $0x2,%eax
40048a: 74 0b je 400497
40048c: eb 10 jmp 40049e
40048e: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
400495: eb 07 jmp 40049e
400497: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
40049e: c9 leaveq
40049f: c3 retq
Can this be done using single thread function?
#include "stdio.h"
#include "pthread.h"
#define NUM_THREAD 5
#define START 1
#define END 100
int n=START; //starting value
int wasted_cycles[NUM_THREAD];
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
void *thread_func(void*data)
{
int num = * ( (int*)data );
char thrname[20] = {0};
int comparewith = ( num%NUM_THREAD );
sprintf(thrname, "%s%02d", "thread", num);
pthread_mutex_lock(&fastmutex);
while(n<=END)
{
if( (n%NUM_THREAD) == comparewith)
{
printf("%s: %03d \t", thrname, n);
if( ( (n>0)&&(n%NUM_THREAD)) ==0 )
printf("\n");
n++;
}
else
{ wasted_cycles[num-1]++; }
pthread_mutex_unlock(&fastmutex);
sched_yield();
}
free(data);
}
main()
{
pthread_t pid[NUM_THREAD+1];
int i;
for(i=1;i<=NUM_THREAD;i++)
{
int *arg = malloc(sizeof(*arg));
*arg=i;
pthread_create(&pid[i], 0, thread_func, (void*)arg);
//printf("Created thread:%d", i);
}
for(i=1;i<=NUM_THREAD;i++)
pthread_join(pid[i], 0);
for(i=0;i
printf("\nWasted(Thread%d): %d", i+1, wasted_cycles[i]);
}
Output
thread01: 001 thread02: 002 thread03: 003 thread04: 004 thread05: 005
thread01: 006 thread02: 007 thread03: 008 thread04: 009 thread05: 010
thread01: 011 thread02: 012 thread03: 013 thread04: 014 thread05: 015
thread01: 016 thread02: 017 thread03: 018 thread04: 019 thread05: 020
thread01: 021 thread02: 022 thread03: 023 thread04: 024 thread05: 025
thread01: 026 thread02: 027 thread03: 028 thread04: 029 thread05: 030
thread01: 031 thread02: 032 thread03: 033 thread04: 034 thread05: 035
thread01: 036 thread02: 037 thread03: 038 thread04: 039 thread05: 040
thread01: 041 thread02: 042 thread03: 043 thread04: 044 thread05: 045
thread01: 046 thread02: 047 thread03: 048 thread04: 049 thread05: 050
thread01: 051 thread02: 052 thread03: 053 thread04: 054 thread05: 055
thread01: 056 thread02: 057 thread03: 058 thread04: 059 thread05: 060
thread01: 061 thread02: 062 thread03: 063 thread04: 064 thread05: 065
thread01: 066 thread02: 067 thread03: 068 thread04: 069 thread05: 070
thread01: 071 thread02: 072 thread03: 073 thread04: 074 thread05: 075
thread01: 076 thread02: 077 thread03: 078 thread04: 079 thread05: 080
thread01: 081 thread02: 082 thread03: 083 thread04: 084 thread05: 085
thread01: 086 thread02: 087 thread03: 088 thread04: 089 thread05: 090
thread01: 091 thread02: 092 thread03: 093 thread04: 094 thread05: 095
thread01: 096 thread02: 097 thread03: 098 thread04: 099 thread05: 100
Wasted(Thread1): 293
Wasted(Thread2): 69
Wasted(Thread3): 300
Wasted(Thread4): 68
Wasted(Thread5): 141
The wasted cycles will vary across executions, confirming randomness in thread scheduling, e.g.
Wasted(Thread1): 3372
Wasted(Thread2): 3582
Wasted(Thread3): 2918
Wasted(Thread4): 3513
Wasted(Thread5): 0
Do you see any CPU wastage in above implementation, ideas on how fix?
switch(i)
{
case 1: break;
case 2: break;
}
Ans: NO.
5. Objdump for below code:
int i=0, j;
switch(i)
{
case 1: j=10; break;
case 2: j=20; break;
}
0000000000400474:
400474: 55 push %rbp
400475: 48 89 e5 mov %rsp,%rbp
400478: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
40047f: 8b 45 f8 mov -0x8(%rbp),%eax
400482: 83 f8 01 cmp $0x1,%eax
400485: 74 07 je 40048e
400487: 83 f8 02 cmp $0x2,%eax
40048a: 74 0b je 400497
40048c: eb 10 jmp 40049e
40048e: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
400495: eb 07 jmp 40049e
400497: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp)
40049e: c9 leaveq
40049f: c3 retq
?? If we add default case, then there are many nop added at the end of main objdump.
6.
int i=0,j, k=20;
int i=0,j, k=20;
switch(i)
{
k=10; //not executed
default: j=40;
case 1: j=10; break;
case 2: j=20; break;
}
printf("k:%d", k);
Output: compiles fine. k:20
If there was printf statement in place of k=10, it would not be printed.
Print 1-100 using five threads, each thread prints different series,
e.g. Thread0: 1,6,11 Thread1: 2,7,12 Thread2: 3,8,13 ...Can this be done using single thread function?
#include "stdio.h"
#include "pthread.h"
#define NUM_THREAD 5
#define START 1
#define END 100
int n=START; //starting value
int wasted_cycles[NUM_THREAD];
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
void *thread_func(void*data)
{
int num = * ( (int*)data );
char thrname[20] = {0};
int comparewith = ( num%NUM_THREAD );
sprintf(thrname, "%s%02d", "thread", num);
pthread_mutex_lock(&fastmutex);
while(n<=END)
{
if( (n%NUM_THREAD) == comparewith)
{
printf("%s: %03d \t", thrname, n);
if( ( (n>0)&&(n%NUM_THREAD)) ==0 )
printf("\n");
n++;
}
else
{ wasted_cycles[num-1]++; }
pthread_mutex_unlock(&fastmutex);
sched_yield();
}
free(data);
}
main()
{
pthread_t pid[NUM_THREAD+1];
int i;
for(i=1;i<=NUM_THREAD;i++)
{
int *arg = malloc(sizeof(*arg));
*arg=i;
pthread_create(&pid[i], 0, thread_func, (void*)arg);
//printf("Created thread:%d", i);
}
for(i=1;i<=NUM_THREAD;i++)
pthread_join(pid[i], 0);
for(i=0;i
printf("\nWasted(Thread%d): %d", i+1, wasted_cycles[i]);
}
Output
thread01: 001 thread02: 002 thread03: 003 thread04: 004 thread05: 005
thread01: 006 thread02: 007 thread03: 008 thread04: 009 thread05: 010
thread01: 011 thread02: 012 thread03: 013 thread04: 014 thread05: 015
thread01: 016 thread02: 017 thread03: 018 thread04: 019 thread05: 020
thread01: 021 thread02: 022 thread03: 023 thread04: 024 thread05: 025
thread01: 026 thread02: 027 thread03: 028 thread04: 029 thread05: 030
thread01: 031 thread02: 032 thread03: 033 thread04: 034 thread05: 035
thread01: 036 thread02: 037 thread03: 038 thread04: 039 thread05: 040
thread01: 041 thread02: 042 thread03: 043 thread04: 044 thread05: 045
thread01: 046 thread02: 047 thread03: 048 thread04: 049 thread05: 050
thread01: 051 thread02: 052 thread03: 053 thread04: 054 thread05: 055
thread01: 056 thread02: 057 thread03: 058 thread04: 059 thread05: 060
thread01: 061 thread02: 062 thread03: 063 thread04: 064 thread05: 065
thread01: 066 thread02: 067 thread03: 068 thread04: 069 thread05: 070
thread01: 071 thread02: 072 thread03: 073 thread04: 074 thread05: 075
thread01: 076 thread02: 077 thread03: 078 thread04: 079 thread05: 080
thread01: 081 thread02: 082 thread03: 083 thread04: 084 thread05: 085
thread01: 086 thread02: 087 thread03: 088 thread04: 089 thread05: 090
thread01: 091 thread02: 092 thread03: 093 thread04: 094 thread05: 095
thread01: 096 thread02: 097 thread03: 098 thread04: 099 thread05: 100
Wasted(Thread1): 293
Wasted(Thread2): 69
Wasted(Thread3): 300
Wasted(Thread4): 68
Wasted(Thread5): 141
The wasted cycles will vary across executions, confirming randomness in thread scheduling, e.g.
Wasted(Thread1): 3372
Wasted(Thread2): 3582
Wasted(Thread3): 2918
Wasted(Thread4): 3513
Wasted(Thread5): 0
Do you see any CPU wastage in above implementation, ideas on how fix?
C again,
void *realloc(void *ptr, size_t size) maymove data to new pointer and free old pointer, return new pointer, OR
keep old pointer, extend it by given size and return old pointer.
Newly allocated memory is uninitialized, realloc(NULL, 10) is safe
write() is faster for writing data to file compared to printf, fprintf, as parsing is required before calling low level write function.
memcpy() is faster than strcpy() as it does not have to check each byte for NULL.
const char *ptr="Hello"; ptr="Cielo"; (OK) ptr[0]='a';(ERR, ptr is pointer to const char)
http://embeddedgurus.com/barr-code/
No comments:
Post a Comment