Tuesday, 16 October 2018

Reverse the given sentence

Reverse the give sentence:


#include <stdio.h>
#include <string.h>

#define STR_BUFFER_256    256
#define ARG_LENGTH        64


int reverse_sentence(char *str, char *str_result, int str_len)
{
        char str_sentence[STR_BUFFER_256] = {'\0'};
        char *arg[ARG_LENGTH] = {0}, *temp = NULL;
        int count = 0, rev_count;

#if 0 // This logic is wrong because strncpy won't return a number of byte written
        int ret = 0;

        ret = strncpy(str_sentence, str, sizeof(STR_BUFFER_256));
        if (ret >= STR_BUFFER_256) {
                printf("Truncation the sentence \n");
        }
#else
        memset(str_sentence, '\0', str_len);
        strncpy(str_sentence, str, str_len);

        if (str_sentence[STR_BUFFER_256 - 1] != '\0') {
                printf("Truncation the sentence \n");
        }

#endif

#ifdef DEBUG
        printf("Original = %s copied varable = %s \n", str, str_sentence);
#endif
        temp = strtok(str_sentence, " ");
        arg[count] = temp;
        count++;

        while (temp && (count < ARG_LENGTH)) {
                temp = strtok(NULL, " ");
                arg[count] = temp;
                count++;
        }


        if (temp && (count >= ARG_LENGTH)) {
                temp = strtok(NULL, " ");
                if (temp != NULL) {
                        printf("No of word is more than %d so taking first %d word only\n", ARG_LENGTH, ARG_LENGTH);
                }
        }

        /* arg[count] last value will be a NULL, but count is point to next to NUll */
        count--;

       /* Count point the sentinal value, decerement to point to the last word */
        count--;
#ifdef DEBUG
        printf("inst cout = %d rev c= %d \n", count, rev_count);
#endif
        for (rev_count = count; rev_count >= 0 ; rev_count--) {
                strncat(str_result, arg[rev_count], str_len);
                if (rev_count != 0) {
                        strncat(str_result, " ", str_len);
                }
        }

        return 0;
}

int main()
{
        char str[STR_BUFFER_256] = "Velraj is coming from chennai";
        char str_result[STR_BUFFER_256] = {'\0'};

        reverse_sentence(str, str_result, sizeof(str_result));
        printf("\n\t\t Original sentence = %s \n\t\t Reverse sentence = %s \n", str, str_result);

        return 0;
}

/* Output:
   ------
   velraj@velraj-HEC41:~/CProgram$ gcc -g sentence_reverse_hcl.c
   velraj@velraj-HEC41:~/CProgram$ ./a.out

   Original sentence = Velraj is coming from chennai
   Reverse sentence = chennai from coming is Velraj
   velraj@velraj-HEC41:~/CProgram$

   '-g' is used to include the symbols, if we need to debug with gdb then compile with -g only give the
   symbol value.

 */

Tuesday, 9 October 2018

Difference between 2 jiffies

What is jiffies:


  • The original kernel timer system (called the "timer wheel) was based on incrementing a kernel-internal value (jiffies) every timer interrupt.
  • The timer interrupt rate (and jiffy increment rate) is defined by a compile-time constant called HZ.
  • Different platforms use different values for HZ.
  • The kernel used 100 as the value for HZ, yielding a jiffy interval of 10 ms.
  • With 2.4, the HZ value for i386 was changed to 1000, yeilding a jiffy interval of 1 ms.
  • Process:
    • When jiffy count is incremented then a process gets time to run.
    • The jiffies are incremented by the timer interrupt that tells the scheduler to reschedule
    •  If the process calls yield() or sleep(), for example, then rescheduling takes place immediately.
    • Thus the context switch to a next available running process not necessarily occurs at the jiffy boundary.
  • It lists /proc/timer_list and /proc/timer_stats.
  • Tick generation:
    • It is updated every tick 
    • tick is triggered by timer/clock interrupt.
    • The interrupt is generated by Intel 8253 or HPET hardware
    • So it won't update until the hardware was property initialized.
  • Difference:
    • There is a better solution to ensure correct jiffy wrap handling in *ALL* kernel code: make jiffy wrap in first five minutes of uptime.
    • #define INITIAL_JIFFIES (0xffffffffUL & (unsigned long)(-300*HZ))
    • Hence jiffies is using the full 32 bit, after that overflow happen.
    • So jiffies.h file comment as maximum jiffie value is (MAX_INT >> 1) is a false comment.
    • Don't use MAX_JIFFY_OFFSET as max value since this is wrong.
    • https://lwn.net/Articles/22874/

Program:


Wrong program:

  • This below code is wrong, because jiffies is using the full 32 bit confirmed by after bootup jiffies overflow in 5 min, 
  • So after bootup just checked the jiffies value, it is using full 32 bit before overflow.
  • Hence below code is wrong, this is wrongly used in some of kernel code.

inline unsigned long jiffies_time_diff(unsigned long start, unsigned long end)
{
    if (end >= start)
        return end - start;
    return end + (MAX_JIFFY_OFFSET - start);
}

Correct program:


inline unsigned long jiffies_time_diff(unsigned long start, unsigned long end)
{  
       unsigned long diff = 0;

       /* This code is handle the overflow also, by converting to long.
            if jiffies start time is 13 and after overflowed end time is 5 then, coverting to sign
            difference value is -8, the 1st complement +1 value of -8 is stored as big value in unsiged diff.
            This is the correct difference */
       diff = (long)end - (long) start;
       return diff;
}
        

Sunday, 7 October 2018

What does _r suffix mean?


  • The suffix "_r" is historical, where the 'r' stood for "reentrant".
  • A computer program or subroutine is called reentrant.
    • if it can be interrupted in the middle of its execution and then safely be called again ("re-entered") before its previous invocations complete execution. 

  • Using global variable inside the function, ISR(interuppt call) may try to access our temporary changed global value in outside.
    • Solution:
      • Use the local variable instead of global variable will clear this issue
    • _r reason:
      • Using _r to make sure global variables are not affected.

  • _r function will be thread safe.
  • EG: strtok vs strtok_r



Return:
The strtok() and strtok_r() functions return a pointer to the next token, or NULL if there are no more tokens.

Attributes:
For an explanation of the terms used in this section, see attributes(7). ┌───────────┬───────────────┬───────────────────────┐ │InterfaceAttributeValue │ ├───────────┼───────────────┼───────────────────────┤ │strtok() │ Thread safety │ MT-Unsafe race:strtok │ ├───────────┼───────────────┼───────────────────────┤ │strtok_r() │ Thread safety │ MT-Safe │ └───────────┴───────────────┴───────────────────────┘

Program:


/* strtok vs strtok_r by Velraj.K
   Check : http://velrajcoding.blogspot.in
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
    char *str1, *str2, *token, *subtoken;
    char *saveptr1, *saveptr2;
    char str_second[256] = {'\0'};
    int j;
    if (argc != 4) {
        fprintf(stderr, "Usage: %s string delim subdelim\n",
                argv[0]);
        exit(EXIT_FAILURE);
    }
    strncpy(str_second, argv[1], sizeof(str_second));
    printf("\n\n\t\t Do the token using strtok_r \n");
    /* use strtok_r */
    for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
        token = strtok_r(str1, argv[2], &saveptr1);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);
        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok_r(str2, argv[3], &saveptr2);
            if (subtoken == NULL)
                break;
            printf(" --> %s\n", subtoken);
        }
    }
    printf("Original value = %s \n", argv[1]);

    printf("\n\n\t\tDo the token using strtok str_second = %s \n", str_second);
    /* Initialize the variable to NULL to start token again with strtok */
    str1 = NULL;
    str2 = NULL;
    token = NULL;
    subtoken = NULL;
    saveptr1 = NULL;
    saveptr2 = NULL;
    /* use strtok */
    for (j = 1, str1 = str_second; ; j++, str1 = NULL) {
        token = strtok(str1, argv[2]);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);
#if 0 // Could not use the 2nd strtok with different delim because it uses the global pointer
        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok(str2, argv[3]);
            if (subtoken == NULL)
                break;
            printf(" --> %s\n", subtoken);
        }
#endif
    }
    exit(EXIT_SUCCESS);
}


Output:


learn$ ./a.out this,isvelraj,check,strok,new , .

                 Do the token using strtok_r
1: this
 --> this
2: isvelraj
 --> isvelraj
3: check
 --> check
4: strok
 --> strok
5: new
 --> new
Original value = this

                Do the token using strtok str_second = this,isvelraj,check,strok,new
1: this
2: isvelraj
3: check
4: strok
5: new

    Tuesday, 2 October 2018

    Stack function argumen & local variable declaration order in stack

    Program:


    /*  Stack function argumen & local variable declaration order in stackprogram by Velraj.K
        Check : http://velrajcoding.blogspot.in
      */
    #include <stdio.h>
    #include <stdlib.h>

    int global = 0;

    int stack_no_argument()
    {
            return 6;
    }

    void stack_no_arg_declar_call(int arg)
    {
            int a;
            int b;

            printf("\n\t\t%s &argc = %p &a = %p &b = %p \n\t\t", __func__, &arg, &a, &b);
    }

    oid stack_no_arg_declar(int arg)
    {
            int a[100];
            int b[200];
            int c[300];
            char chr[100];   /* Seems stack also it is taking extra bye, use only int is continue.
                              * but mixing char inbetween get extra bye on first a int and then this variable */
            int d[100];
            void *ptr = NULL;
            int *ptr_int;

            ptr = malloc(100);
            ptr_int = b;

            *(ptr_int + 200) = 1;
            printf("\n\t\t &a[0] = %p &a[99] = %p \n\t\t &b[0] = %p &b[199] = %p\n\t\t &c[0] = %p &c[299] = %p\n\t\t",
                            &a[0], &a[99], &b[0], &b[199], &c[0], &c[299]);

            printf("\n\t\t chr[0] = %p, &chr[99] = %p\n\t\t &d[0] = %p &d[99] = %p\n\t\t global = %p\n\t\t malloc= %p\n\t\t",
                            &chr[0], &chr[99], &d[0], &d[99],
                            &global, ptr);
            printf("\n\t\t &ptr = %p \n\t\t &ptr_int = %p \n\t\t",
                            &ptr, &ptr_int);
            printf("\n\t\t argc = %p \n\t\t a[0] = %d c[0] = %d \n\n",
                            &arg, a[0], c[0]);
           stack_no_arg_declar_call(100);
    }

    int stack_argument_seque(int a, int b, char ch, float *flo)
    {
            b = a + ch;
            printf("Inside the function \n");
            return 10;
    }



    int main()
    {
            float value = 0.0;
            int ret = 0;
    /*
            ---- snip -----
            fstps   -20(%ebp)
            movl    $0, -16(%ebp)
            leal    -20(%ebp), %eax
            pushl   %eax
            pushl   $99   
            pushl   $2
            pushl   $1
            call    stack_argument_seque
            ---- snip -----
            Argument pushed into stack from right to left.
            Note: ASCII value of 'c' is 99.
    */

    int stack_argument_seque(int a, int b, char ch, float *flo)
    {
            b = a + ch;
            printf("Inside the function \n");
            return 10;
    }



    int main()
    {
            float value = 0.0;
            int ret = 0;
    /*
            ---- snip -----
            fstps   -20(%ebp)
            movl    $0, -16(%ebp)
            leal    -20(%ebp), %eax
            pushl   %eax
            pushl   $99   
            pushl   $2
            pushl   $1
            call    stack_argument_seque
            ---- snip -----
            Argument pushed into stack from right to left.
            Note: ASCII value of 'c' is 99.
    */

    int stack_argument_seque(int a, int b, char ch, float *flo)
    {
            b = a + ch;
            printf("Inside the function \n");
            return 10;
    }



    int main()
    {
            float value = 0.0;
            int ret = 0;
    /*
            ---- snip -----
            fstps   -20(%ebp)
            movl    $0, -16(%ebp)
            leal    -20(%ebp), %eax
            pushl   %eax
            pushl   $99   
            pushl   $2
            pushl   $1
            call    stack_argument_seque
            ---- snip -----
            Argument pushed into stack from right to left.
            Note: ASCII value of 'c' is 99.
    */


            ret = stack_argument_seque(1, 2, 'c', &value);
            stack_no_argument();
            stack_no_arg_declar(10);
    }


    Output:
       ------
       velraj@velraj-HEC41:~/CProgram$ ./a.out
    Inside the function

                     &a[0] = 0xbfdd319c &a[99] = 0xbfdd3328
                     &b[0] = 0xbfdd332c &b[199] = 0xbfdd3648
                     &c[0] = 0xbfdd364c
                    global = 0x804a02c
                      malloc= 0x942c410
                    a[0] = 0 c[0] = 0


    After add the char inbetween:
    --------------------------
    velraj@velraj-HEC41:~/CProgram$ ./a.out
    Inside the function
    Output:
       ------
       velraj@velraj-HEC41:~/CProgram$ ./a.out
    Inside the function

                     &a[0] = 0xbfdd319c &a[99] = 0xbfdd3328
                     &b[0] = 0xbfdd332c &b[199] = 0xbfdd3648
                     &c[0] = 0xbfdd364c
                    global = 0x804a02c
                      malloc= 0x942c410
                    a[0] = 0 c[0] = 0


    After add the char inbetween:
    --------------------------
    velraj@velraj-HEC41:~/CProgram$ ./a.out
    Inside the function


                     &a[0] = 0xbfed0ac8 &a[99] = 0xbfed0c54
                     &b[0] = 0xbfed0de8 &b[199] = 0xbfed1104
                     &c[0] = 0xbfed1108 &c[299] = 0xbfed15b4
                     chr[0] = 0xbfed15b8, &chr[99] = 0xbfed161b
                     &d[0] = 0xbfed0c58 &d[99] = 0xbfed0de4
                     global = 0x804a02c
                     malloc= 0x855b410
                     a[0] = 0 c[0] = 1

            Here we are wring b+200 but it write on c[0], hece a first b second and 3rd is c, since stack botton start on top, hence address wise c a is long from stack.

            Output current:
            --------------
    velraj@velraj-HEC41:~/CProgram$ ./a.out
    Inside the function


                     &a[0] = 0xbf85fa58 &a[99] = 0xbf85fbe4
                     &b[0] = 0xbf85fd78 &b[199] = 0xbf860094
                     &c[0] = 0xbf860098 &c[299] = 0xbf860544
                   
                     chr[0] = 0xbf860548, &chr[99] = 0xbf8605ab
                     &d[0] = 0xbf85fbe8 &d[99] = 0xbf85fd74
                     global = 0x804a02c
                     malloc= 0x80e9410
                   
                     &ptr = 0xbf85fa50
                     &ptr_int = 0xbf85fa54
                   
                     argc = 0xbf8605c0
                     a[0] = 0 c[0] = 1


                    stack_no_arg_declar_call &argc = 0xbf85fa40 &a = 0xbf85fa24 &b = 0xbf85fa28


    Diagram to understand:



    Vim editor tips

    Split into 2 screen:

      

    • split your screen in multiple files horizontal: :sp <filepath>\

    • switch between splitscreens with Ctrl+W

    •  :vsp or :vp is for vertical split. Then use Ctrl+W <ARROW_KEYS> to move in panes.

    :n -> Move to next file
    :N -> Move to previous file

    Vimdiff colorscheme:


    List all the installed color schemes in VIM:

    Type
    :colorscheme then Space followed by TAB.
    or as Peter said,
    :colorscheme then Space followed by CTRLd
    or path: /usr/share/vim/vim74/colors/b

    Load different colorscheme when using vimdiff


    if &diff
        colorscheme some_other_scheme
    endif

    Hence the .vimrc file content:


    " Set colorscheme only to Vimdiff if use from command line " Check the colorschme for vimdiff and collected below "      pablo -> good, slate -> ok, blue -> Very dark
    if &diff     colorscheme pablo endif

    Complete .vimrc file content:



    "Indents braces set cindent
    "Indents by 4 spaces set shiftwidth=4
    "Prevents spaces from being converted to tabs "set expandtab
    "To hightligth the search word" set hlsearch
    " Red line verital mark "set cc=80
    " Once it reace 79 it will automatically come to next line "set tw=79
    " always add a space after comma " Enable it only if you keep on forgetting space after comma " inoremap , ,<space>
    " strcpy, strncpy, strcat, strncat, sprintf, strtok, memcpy are banned APIs. " Highlight them as Error, to prevent accidental usage. match Error /\<strcpy\>\|\<strncpy\>\|\<strcat\>\|\<strncat\>\|\<sprintf\>\|\<strtok\>\|\<memcpy\>/
    fun! VerifySyntaxError()         highlight default link LinuxError ErrorMsg
            syn match LinuxError / \+\ze\t/     " spaces before tab         syn match LinuxError /\%>80v[^()\{\}\[\]<>]\+/ " virtual column 81 and more
            " Highlight trailing whitespace, unless we're in insert mode and the         " cursor's placed right after the whitespace. This prevents us from having         " to put up with whitespace being highlighted in the middle of typing         " something         autocmd InsertEnter * match LinuxError /\s\+\%#\@<!$/         autocmd InsertLeave * match LinuxError /\s\+$/ endfunction
    map <F5> :call VerifySyntaxError()<CR>
    " Vel Adding list : " For ctags, to use ctrl + ] option set cscopetag
    " Set colorscheme only to Vimdiff if use from command line " Check the colorschme for vimdiff and collected below "      pablo -> good, slate -> ok, blue -> Very dark
    if &diff     colorscheme pablo endif