- Default arguments in virtual functions - Always the default argument mentioned in the base class function declaration is used. The default arguments are not part of class signature. Default arguments is added to the function call at compile time. But the function call resolution is made at run time.
- Why virtual destructor is used.
- Difference between static and dynamic casting. Dynamic cast will give a compile error if the class is not polymorphic.
- Keyword 'auto' - This is good while creating iterators to avoid the long initializations
- Good link for c++ reference
- Name Mangling and extern “C” in C++
- const functions in c++
- static const in c++
- abstract data types?
- Operator overloading
- we can restrict dynamic allocation of objects of a class by declaring a private new and new[] operators.
- Operators which cannot be overloaded
- . operator, -> operator, ?: operator, :: operator
- Conversion operators
- const functions in c++
- Smart pointer in c++
- Virtual functions
- http://blog.httrack.com/blog/2014/05/09/a-basic-glance-at-the-virtual-table/
- http://www.studytonight.com/cpp/virtual-functions.php
- Virtual Classes
- Constructors
- Constructors and array of objects with new
- If One class
- http://stackoverflow.com/questions/8312054/constructors-and-array-of-object-in-c
- int *n = new int[3]{1,2,3};
- A *a = new A[3]{{1,2},{3,4},{5,6} // This invokes constructor with 2 arguments for 3 objects.
- Copy constructor argument should be constant
- Conversion constructor
- The 'explicit' keyword
- Constructors cannot be virtual and can be private
- Templates
- Template specialization
- Passing non type arguments to templates
- The string class dynamically increases or decreases the memory for characters.
- Conversion operators
- Anatomy of assignment operator - good
Wednesday, April 27, 2016
C++
Monday, April 25, 2016
program, assembly, simple1.c
simple1.c
int add(int i, int j);
int main()
{
int i, j;
i++;
j = 10;
j = i;
j = add(i,j);
return 0;
}
int add(int i, int j)
{
int result;
result = i+j;
return result;
}
int main()
{
int i, j;
i++;
j = 10;
j = i;
j = add(i,j);
return 0;
}
int add(int i, int j)
{
int result;
result = i+j;
return result;
}
simple1.s
.file "simple1.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
addl $1, -8(%rbp)
movl $10, -4(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %esi
movl %eax, %edi
call add
movl %eax, -4(%rbp)
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.globl add
.type add, @function
add:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -20(%rbp)
movl %esi, -24(%rbp)
movl -24(%rbp), %eax
movl -20(%rbp), %edx
addl %edx, %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size add, .-add
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",@progbits
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
addl $1, -8(%rbp)
movl $10, -4(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %edx
movl -8(%rbp), %eax
movl %edx, %esi
movl %eax, %edi
call add
movl %eax, -4(%rbp)
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.globl add
.type add, @function
add:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -20(%rbp)
movl %esi, -24(%rbp)
movl -24(%rbp), %eax
movl -20(%rbp), %edx
addl %edx, %eax
movl %eax, -4(%rbp)
movl -4(%rbp), %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size add, .-add
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",@progbits
nm simple1.o
0000000000000032 T add
0000000000000000 T main
0000000000000000 T main
proram, assembly, simple.c
Simple.c
int main()
{
int i, j;
i++;
j = 10;
j = i;
return 0;
}
{
int i, j;
i++;
j = 10;
j = i;
return 0;
}
Simple.s
.file "simple.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
addl $1, -8(%rbp)
movl $10, -4(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",@progbits
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
addl $1, -8(%rbp)
movl $10, -4(%rbp)
movl -8(%rbp), %eax
movl %eax, -4(%rbp)
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
.section .note.GNU-stack,"",@progbits
nm simple.o
0000000000000000 T main
Friday, April 22, 2016
Kernel Synchronization
- critical regions: Code paths that access and manipulate shared data are called critical regions
- atomic operation: operations complete without interruption as if the entire critical region were one indivisible instruction
- Race condition: it is the condition when two threads of execution to be simultaneously executing within the same critical region.
- If the critical region is a very minimal instruction, making the execution as atomic operation will avoid the race condition. For eg, i++ will be performed by 3 or 4 instructions in assembly language. This can be made as an atomic operation for synchronization.
- The kernel provides two sets of interfaces for atomic operations—one that operates on integers and another that operates on individual bits.These interfaces are implemented on every architecture that Linux supports. Most architectures contain instructions that provide atomic versions of simple arithmetic operations. Other architectures, lacking direct atomic operations, provide an operation to lock the memory bus for a single operation, thus guaranteeing that another memory-affecting operation cannot occur simultaneously.
- Generally, a few instructions can be made atomic by the processor. When a huge instructions are to be synchronized, a locking mechanism is required. In this case only the locking operation will be atomic.
- Locking mechanisms can be different that when a thread finds that a critical region is locked, it can busy wait(eg, spin lock) or sleep.
- On the popular x86 architecture, locks are implemented using such an instruction called compare and exchange.
- Causes of concurrency in user space programs.
- true concurrency occurs because of multi processors.
- pseudo-concurrency occurs because of preemption(or yielding) or receiving of signals in a user space program.
- Causes of concurrency in kernel space programs.
- Interrupts— An interrupt can occur asynchronously at almost any time, interrupting the currently executing code.
- Softirqs and tasklets— The kernel can raise or schedule a softirq or tasklet at almost any time, interrupting the currently executing code.
- Kernel preemption— Because the kernel is preemptive, one task in the kernel can preempt another.
- Sleeping and synchronization with user-space— A task in the kernel can sleep and thus invoke the scheduler, resulting in the running of a new process.
- Symmetrical multiprocessing— Two or more processors can execute kernel code at exactly the same time.
- The term lock contention, or simply contention, describes a lock currently in use but that another thread is trying to acquire.
- spin lock:
- A spin lock is a lock that can be held by at most one thread of execution.
- If a thread of execution attempts to acquire a spin lock while it is already held, which is called contended, the thread busy loops—spins—waiting for the lock to become available.
- It is not wise to hold a spin lock for a long time.This is the nature of the spin lock: a lightweight single-holder lock that should be held for short durations.
- Making the process to sleep if the lock is already contended incurs a bit of overhead—most notably the two context switches required to switch out of and back into the blocking thread, which is certainly a lot more code than the handful of lines used to implement a spin lock.Therefore, it is wise to hold spin locks for less than the duration of two context switches.
- On uniprocessor machines, the locks compile away and do not exist; they simply act as markers to disable and enable kernel preemption. If kernel preempt is turned off, the locks compile away entirely.
- Spin locks can be used in interrupt handlers, whereas semaphores cannot be used because they sleep.
- If a lock is used in an interrupt handler, you must also disable local interrupts (interrupt requests on the current processor) before obtaining the lock. Otherwise, it is possible for an interrupt handler to interrupt kernel code while the lock is held and attempt to reacquire the lock.The interrupt handler spins, waiting for the lock to become
available.The lock holder, however, does not run until the interrupt handler completes. This is an example of the double-acquire deadlock. Note that you need to disable interrupts only on the current processor. If an interrupt occurs on a different processor, and it spins on the same lock, it does not prevent the lock holder (which is on a different processor) from eventually releasing the lock. - Because a bottom half might preempt process context code, if data is shared between a bottom-half process context, you must protect the data in process context with both a lock and the disabling of bottom halves. Likewise, because an interrupt handler might preempt a bottom half, if data is shared between an interrupt handler and a bottom half, you must both obtain the appropriate lock and disable interrupts
- reader-writer spin lock
Sunday, April 10, 2016
Kernel Stack
- https://www.kernel.org/doc/Documentation/x86/kernel-stacks
Like all other architectures, x86_64 has a kernel stack for every active thread. These thread stacks are THREAD_SIZE (2*PAGE_SIZE) big. These stacks contain useful data as long as a thread is alive or a zombie.
While the thread is in user space the kernel stack is empty except for the thread_info structure at the bottom.
Sunday, April 03, 2016
General Scraps
- Processor priority in Linux
- The first is the nice value, a number from -20 to +19 with a default of 0. Larger nice values correspond to a lower priorityyou are being nice to the other processes on the system. Processes with a lower nice value (higher priority) run before processes with a higher nice value (lower priority). The nice value also helps determine how long a timeslice the process receives. A process with a nice value of -20 receives the maximum possible timeslice, whereas a process with a nice value of 19 receives the minimum possible timeslice. Nice values are the standard priority range used in all Unix systems.
- The second range is the real-time priority. The values are configurable, but by default range from 0 to 99. All real-time processes are at a higher priority than normal processes.
- Real Time values + nice value together.
- Real Time process command
- http://linux.die.net/man/1/chrt
- http://unix.stackexchange.com/questions/154867/real-time-processes-scheduling-in-linux
- The chrt command
- To set scheduling policy to
SCHED_FIFO, enter:chrt -f -p [1..99] {pid}To set scheduling policy toSCHED_RR, enter:chrt -r -p [1..99] {pid} asmlinkage keyworkd in system call
system call is reentrant
Seeing assembly and register values in GDB and description about assembly code
- re-entrant and thread safe functions.
- Variadic functions and variadic macro funtions
- Volatile type specifier - http://www.geeksforgeeks.org/understanding-volatile-qualifier-in-c/
Subscribe to:
Posts (Atom)