Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts

Thursday, November 5, 2020

Red Zone - Stack Frame (x86-64)

 https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685

https://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64






Kernel Threads

  • kthreadd (pid = 2) created by kernel (pid = 0) during boot
  • kthreadd helps in creating other kernel threads which are required to run periodically/asynchronously
  • "ps" shows kernel threads
  • Everything under [square bracket] are kernel threads

sw0:FID128:root> ps -eaf
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 01:21 ?        00:00:00 init [5]
root         2     0  0 01:21 ?        00:00:00 [kthreadd]
root         3     2  0 01:21 ?        00:00:00 [ksoftirqd/0]
root         4     2  0 01:21 ?        00:00:00 [kworker/0:0]

  • All calls from user-space to create a new process (including "create_thread" in kthreadd), will end up in do_fork call which internally calls copy_process

Thursday, August 27, 2020

Sunday, October 6, 2019

How to Print in Makefile

Source: https://stackoverflow.com/questions/11775733/how-can-i-print-message-in-makefile/11776179


 15 # for TRACEGEN
 16 include $(MAKEDIR)/Tools.make
 17
 18 ifeq ($(CONFIG_SOMETHING),y)
 19 EXTRA_CFLAGS += -fsanitize=kernel-address
 20 $(info ************  TEST VERSION ************)
 21 else
 22 $(info ************  ELSE VERSION ************)
 23 endif

$(info your_text) : Information. This doesn't stop the execution.
$(warning your_text) : Warning. This shows the text as a warning.
$(error your_text) : Fatal Error. This will stop the execution.

To print a variable in Makefile:

 18 $(info $$CONFIG_VAR1 is [${CONFIG_VAR1}])
 19 $(info $$CONFIG_VAR2 is [${CONFIG_VAR2}])


Thursday, August 20, 2015

Grep with function name (with different colors) recursively

#!/bin/csh

#

# Maximum can be any parameters (if user has given '*' as files)
#
if ( $#argv < 1 ) then
    echo "\n[USAGE]: $0 <pattern> <files>\n";
    exit
endif

#awk -v re=$1 '/^[[:alpha:]]/{f=FNR"-"$0} $0~re{printf "%s\n%d:%s\n--\n",f,FNR,$0; f="" }' $2
#awk -v re='CANMIC_MX_LOCK' '/^[[:alpha:]]/{f=FNR"-"$0} $0~re{printf "\033[1;31m%s\n\033[34m%d:\033[0m%s\n--\n",f,FNR,$0; f="" "\033[0m" }' *
#awk -v re=$1 '/^[[:alpha:]]/{f=FNR"-"$0} $0~re{printf "\033[1;31m%s\n\033[34m%d:\033[0m%s\n--\n",f,FNR,$0; f="" "\033[0m" }' $2
    foreach i (`find . -name "*" -type f -print`)
    awk -v re=$1 '/^[[:alpha:]]/{f=FNR"-"$0} $0~re{printf "\033[1;32m[%15s]\t\033[1;31m%-64s\t\033[34m%s\n--\033[0m\n",FILENAME,f,$0; f="" }' $i
    end

Output:
[./canmic/canmic_err.c] 53-canmic_state_set(int newstate, int *oldstate)                                CANMIC_MX_LOCK();
--
[./canmic/canmic_err.c] 77-canmic_stateful_write(char *blkdata, size_t blksize, int blknmbr)            CANMIC_MX_LOCK();
--
[./canmic/canmic_err.c] 93-canmic_stateful_dirty(scnMsg_t *scnmsg)                                      CANMIC_MX_LOCK();
--
[./canmic/canmic_err1.h]                                                                                #define CANMIC_MX_LOCK()        do {    \
--
[./canmic/canmic_err.h]                                                                         #define CANMIC_MX_LOCK()        do {    \

Friday, December 7, 2012

Multithreading - Part 2: Synchronization


Consider the program which we mentioned in "Multithreading - Part 1: Basics"


Program:

#include <stdio.h>
#include <pthread.h>


int gvar;

void* t1_fun(void *msg)
{
    int i;
    for(i = 0; i < 10; i++)
    {   
        gvar++;
        /*printf("[%d:%s] : gvar = %d.\n", pthread_self(), (char*) msg, gvar);*/
        printf("[%d:%s] : gvar = %d.\n", (long int)syscall(224), (char*) msg, gvar);
    }   
}

int main()
{
    pthread_t t1, t2; 
    char *msg1 = "thread1";
    char *msg2 = "thread2";

    int rc1 = pthread_create(&t1, NULL, t1_fun, (void *) msg1);
    if( rc1 ) { printf("Error for thread 1.\n"); perror("pthread_create"); }
    int rc2 = pthread_create(&t2, NULL, t1_fun, (void *) msg2);
    if( rc2 ) { printf("Error for thread 1.\n"); perror("pthread_create"); }

    /* If the 2nd arg is NOT NULL, the return value of t1 and t2 will be stored there.
     * This pthread_join will suspend the main thread until the t1/t2 completes, terminates or by calling
     * pthread_exit. 
     */
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);    
    printf("Threads execution over.\n");
    return 0;
}

NOTE that if there is no load in the system, this program might print the value of "gvar" as 20 as expected (each thread increments gvar 10 times; hence 20).
But, if you increase the load in the system or if you increase the count in the for loop (replace the count 10 with 50), you can see the threads will fight each other to increment the global variable "gvar". At the  end of the program, if you see, the "gvar" will not be "100" as expected; but rather less (see below).


[5164:thread1] : gvar = 95.
[5164:thread1] : gvar = 96.
...
...
[5165:thread2] : gvar = 95.
[5165:thread2] : gvar = 97.


This kind of situation is called "race condition" where two or more threads will race with each other to change the state of a variable without bothering about the other one.

To avoid this, we have to use mutex.

Mutex (ONLY BETWEEN THREADS IN A SINGLE PROCESS; NOT ACROSS PROCESSES LIKE SEMAPHORE):
Mutexes are used to prevent data inconsistencies due to operations by multiple threads upon the same memory area performed at the same time or to prevent race conditions where an order of operation upon the memory is expected. A contention or race condition often occurs when two or more threads need to perform operations on the same memory area, but the results of computations depends on the order in which these operations are performed. Mutexes are used for serializing shared resources such as memory. Anytime a global resource is accessed by more than one thread the resource should have a Mutex associated with it. Once can apply a mutex to protect a segment of memomry ("critical region") from other threads. Mutexes can be applied only to threads in a single process and do not work between processes as do semaphores.

Modified Program with Mutex:


#include <stdio.h>
#include <pthread.h>


/* Note scope of variable and mutex are the same */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int gvar;
void* t1_fun(void *msg)
{
    int i;
    for(i = 0; i < 100; i++)
    {   
        pthread_mutex_lock( &mutex );
        gvar++;
        /*printf("[%d:%s] : gvar = %d.\n", pthread_self(), (char*) msg, gvar);*/
        printf("[%d:%s] : gvar = %d.\n", (long int)syscall(224), (char*) msg, gvar);
        pthread_mutex_unlock( &mutex );
    }   
}
...
...
Program Output:
$> gcc sample.c -lpthread
$> ls
a.out sample.c

$> ./a.out

[5164:thread1] : gvar = 99.
[5164:thread1] : gvar = 100.
...
...
[5165:thread2] : gvar = 199.
[5165:thread2] : gvar = 200.
Now, no matter how much ever you try executing this program, "gvar" at the end of the program will be always 200 (if you specify 100 as loop count in for loop).
NOTE THAT THE SCOPE OF THE VARIABLE AND THE MUTEX VARIABLE IS SAME. MEANS, GLOBAL VARIABLE PROTECTION SHOULD USE GLOBAL MUTEX VARIABLE!!

Multithreading - Part 1: Basics


Threads: Light-weight Processes (LWP); mostly useful if created in user-space.

Program:

#include <stdio.h>
#include <pthread.h>

int gvar;
void* t1_fun(void *msg)
{
    int i;
    for(i = 0; i < 10; i++)
    {   
        gvar++;
        /*printf("[%d:%s] : gvar = %d.\n", pthread_self(), (char*) msg, gvar);*/
        printf("[%d:%s] : gvar = %d.\n", (long int)syscall(224), (char*) msg, gvar);
    }   
}

int main()
{
    pthread_t t1, t2; 
    char *msg1 = "thread1";
    char *msg2 = "thread2";

    int rc1 = pthread_create(&t1, NULL, t1_fun, (void *) msg1);
    if( rc1 ) { printf("Error for thread 1.\n"); perror("pthread_create"); }
    int rc2 = pthread_create(&t2, NULL, t1_fun, (void *) msg2);
    if( rc2 ) { printf("Error for thread 1.\n"); perror("pthread_create"); }
    
    printf("Threads execution over.\n");
    return 0;
}

Points to Note:
1. The function prototype of the thread should be
 void * fun( void * args);
2. Single arguments (like above) can be directly passed after casting to "void *"; where as
multiple arguments can be passed in the form of structures.
3. To print the LWP (thread) ID, I am using the method
(long int) syscall (224) ==> This is the system call for "gettid" system call.
And note, pthread_self() returns "pthread_t"; and not the "thread id".
4. And for both the threads, I can give the same function (t1_fun).
5. Format of pthread_create: pthread_create(&t1, <thread_attr>, <function>, <function_args>)

Program Output:
$> gcc sample.c -lpthread
$> ls
a.out sample.c

$> ./a.out
Threads execution over.
[5164:thread1] : gvar = 1.
[5164:thread1] : gvar = 2.

Why such output?:
The reason is, we have "just triggered the threads and did not bother about them after that".
To make sure, we get all the printfs of both the threads, the main thread should "wait" for those two threads to "join" it.
Hence, if you provide "pthread_join" call for both the threads, you main thread will not exit UNTIL both the threads completes its execution.

...
...

    int rc2 = pthread_create(&t2, NULL, t1_fun, (void *) msg2);
    if( rc2 ) { printf("Error for thread 1.\n"); perror("pthread_create"); }
    
    /* If the 2nd arg is NOT NULL, the return value of t1 and t2 will be stored there.
     * This pthread_join will suspend the main thread until the t1/t2 completes, terminates or by calling
     * pthread_exit. 
     */
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    printf("Threads execution over.\n");
    return 0;
}


Program Output:
$> gcc sample.c -lpthread
$> ls
a.out sample.c

$> ./a.out

[5164:thread1] : gvar = 1.
[5164:thread1] : gvar = 2.

[5164:thread1] : gvar = 3.
[5164:thread1] : gvar = 4.

[5164:thread1] : gvar = 5.
[5164:thread1] : gvar = 6.

...
...

[5165:thread2] : gvar = 19.
[5165:thread2] : gvar = 20.

Tuesday, October 11, 2011

Sample vimrc file

For vimdiff colorschemes:
- Download github & molokai like below

curl -fLo ~/.vim/colors/molokai.vim --create-dirs https://raw.githubusercontent.com/tomasr/molokai/master/colors/molokai.vim
curl -fLo ~/.vim/colors/github.vim --create-dirs https://raw.githubusercontent.com/endel/vim-github-colorscheme/master/colors/github.vim
Then add the below in .vimrc file
if &diff
"   colorscheme github
    colorscheme molokai
endif
<or> ":colorscheme github" diff mode

syntax enable
set incsearch
set nocompatible
set showcmd
set hlsearch
set ai
set si
set ts=4 sw=4 smarttab
set nu
"set nowrap
set formatoptions+=r
set softtabstop=4
set smartindent
set autoindent
set showmatch
"set cursorline

source $HOME/.vim/plugin/taglist.vim
source $HOME/.vim/plugin/comments.vim

"highlight DiffAdd term=reverse cterm=bold ctermbg=white ctermfg=black
"highlight DiffChange term=reverse cterm=bold ctermbg=cyan ctermfg=black
"highlight DiffText term=reverse cterm=bold ctermbg=gray ctermfg=black
"highlight DiffDelete term=reverse cterm=bold ctermbg=cyan ctermfg=black

nnoremap <silent> <F1> :TlistToggle<CR>
"map <C-v><C-v> : vs<cr>
"map <C-q> : q<cr>

command CDC lcd %:p:h

hi LineNr   ctermfg=darkyellow
"hi Function ctermfg=cyan
hi Function ctermfg=yellow
"hi Type  ctermfg=cyan
hi Type  ctermfg=lightred
hi String ctermfg=darkgreen
"hi String ctermfg=150
hi Number ctermfg=brown
"hi Operator ctermfg=brown
hi Search ctermbg=yellow
hi Conditional ctermfg=green
hi Comment ctermfg=lightblue
"""
"if &term =~ "xterm\\|rxvt"
  " use an orange cursor in insert mode
  "let &t_SI = "\<Esc>]12;orange\x7"
  " use a red cursor otherwise
  "let &t_EI = "\<Esc>]12;red\x7"
  "silent !echo -ne "\033]12;red\007"
  "" reset cursor when vim exits
  "autocmd VimLeave * silent !echo -ne "\033]112\007"
  " use \003]12;gray\007 for gnome-terminal and rxvt up to version 9.21
"endif
highlight Cursor ctermfg=yellow ctermbg=black
"highlight iCursor guifg=white guibg=steelblue
"set guicursor=n-v-c:block-Cursor
"set guicursor+=i:ver100-iCursor
"set guicursor+=n-v-c:blinkon0
"set guicursor+=i:blinkwait10
"""

" Copyright abbreviations
iab cfn /*<CR>Function<CR><CR>Description<CR><CR>Parameter(s)<CR><CR>Return Value<CR>/<Up><Up><Up><Up><Up><Up>
iab todo // TODO Remove this
iab cpr Broadcom Proprietary and Confidential. Copyright © 2019 Broadcom.<CR>All Rights Reserved.<CR>The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.

iab testbin TOPDIR<TAB>= ../../..<CR>MAKEDIR<TAB>= $(TOPDIR)/make<CR><CR>include $(MAKEDIR)/Tools.make<CR>include $(MAKEDIR)/Targets.make<CR>include $(MAKEDIR)/Fabos.make<CR>include $(MAKEDIR)/Man.make<CR><CR>TESTBIN = testbin<CR>TESTBIN_SRCS = testbin.c<CR>TESTBIN_OBJS = $(TESTBIN_SRCS:.c=.o)<CR><CR>$(TESTBIN): $(TESTBIN_OBJS)<CR><TAB>$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)<CR>all:: $(TESTBIN)<CR><CR>clean::<CR><TAB>rm $(TESTBIN) $(TESTBIN_OBJS)


iab log_this #define LOG_THIS(format, ...) { \<CR>if (access("/harish", F_OK) != -1) { \<CR>char buf1[128] = {}; char buf2[256] = {}; \<CR>char tbuf[20] = {}; time_t now = time(0); struct tm *sTm = gmtime(&now); \<CR>strftime(tbuf, sizeof (tbuf), "%Y-%m-%d %H:%M:%S", sTm); \<CR>snprintf(buf1, sizeof (buf1), "[%s %s:%d]" format, tbuf, __func__, __LINE__, ##__VA_ARGS__); \<CR>snprintf(buf2, sizeof (buf2), "echo '%s' >> /harish_log", buf1); \<CR>system(buf2); } }


function! LoadCscope()
  let db = findfile("cscope.out", ".;")
  if (!empty(db))
    let path = strpart(db, 0, match(db, "/cscope.out$"))
    set nocscopeverbose " suppress 'duplicate connection' error
    exe "cs add " . db . " " . path
    set cscopeverbose
  " else add the database pointed to by environment variable
  elseif $CSCOPE_DB != ""
    cs add $CSCOPE_DB
  endif
endfunction
"au BufEnter /* call LoadCscope()

" http://cscope.sourceforge.net/cscope_maps.vim
nmap <C-\>ss :cs find s <C-R>=expand("<cword>")<CR><CR>
"nmap <C-\>g :cs find g <C-R>=expand("<cword>")<CR><CR>
nmap <C-\>cc :cs find c <C-R>=expand("<cword>")<CR><CR>
nmap <C-\>tt :cs find t <C-R>=expand("<cword>")<CR><CR>
"nmap <C-\>e :cs find e <C-R>=expand("<cword>")<CR><CR>
nmap <C-\>ff :cs find f <C-R>=expand("<cfile>")<CR><CR>
"nmap <C-\>i :cs find i ^<C-R>=expand("<cfile>")<CR>$<CR>
"nmap <C-\>d :cs find d <C-R>=expand("<cword>")<CR><CR>
nmap <C-\>s :cs find s
nmap <C-\>g :cs find g
nmap <C-\>c :cs find c
nmap <C-\>t :cs find t
nmap <C-\>e :cs find e
nmap <C-\>f :cs find f
nmap <C-\>i :cs find i
nmap <C-\>d :cs find d

" quick fix options
nmap qf :set cscopequickfix=s-,c-,d-,i-,t-,e-
nmap noqf :set cscopequickfix=""
nmap cw :cwindow

"function! AddCscope()
    "echom "Adding CSCOPE file.. please wait"
    "silent! exec "r!goto_base_ws"
    ":cs add cscope.files
"endfunction
"nnoremap <silent> <F3> :call AddCscope()<CR>
"nnoremap <F3> :! ~/bin/goto_base_ws && cd vobs/projects/springboard/fabos <CR>:cs add cscope.files<CR>