Articles by Xiaojie Yuan

  1. [Linux] Bpftrace

    Terminologies

    • Static Tracing
    • tracepoints are put explicitly into the source code, the tracing framework can then enable or disable those tracepoints at run time as desired
    • Dynamic Tracing
    • tracepoints are injected into a running system, usually in the form of a breakpoint instruction.

    Background

    linux-tracing-timeline.png

    linux-tracing-tracing-tech-stack.png Introduction

    bpftrace …

  2. "[Linux] Generate kernel crash dump"

    Steps

    1. Make sure following configs are on/off for current kernel
    # CONFIG_KASAN is not set
    CONFIG_RELOCATABLE=y
    CONFIG_KEXEC=y
    CONFIG_CRASH_DUMP=y
    CONFIG_DEBUG_INFO=y
    CONFIG_MAGIC_SYSRQ=y
    CONFIG_PROC_VMCORE=y
    
    1. Install kexec and crash tool
    $ sudo apt install kexec-tools makedumpfile crash
    
    1. Add 'crashkernel' parameter to grub
    $ sudo vi /etc/default/grub
    GRUB_CMDLINE_LINUX_DEFAULT="crashkernel …
  3. "[LeetCode][008] String to Integer (atoi)"

    #include <limits.h>
    
    #define INT_MAX_DIV_BY_10 (INT_MAX / 10)
    #define INT_MAX_REM_BY_10 (INT_MAX % 10)
    #define INT_MIN_DIV_BY_10 (INT_MIN / 10)
    #define INT_MIN_REM_BY_10 (INT_MIN % 10)
    
    int myAtoi(char * str){
        char *p = str, c;
        int s = 1;
        int d;
        int v = 0;
    
        while (c = *p++) {
            if (c == ' ')
                continue;
    
            if ((c == '+' || c == '-') && *p >= '0' && *p <= '9') {
                if (c …
  4. "[LeetCode][322] Coin Change"

    Formular:
      dp[i] = MIN( dp[i - coins[j]] + 1 ) (j: [0, coinSize - 1])
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    
    int coinChange(int *coins, int coinSize, int amount)
    {
            int i, j;
            int *dp = calloc(amount + 1, sizeof(int));
            int min_so_far;
            int prev;
            int result;
    
            dp[0] = 0;
    
            for …
  5. "[Design Pattern] Summary"

    Singleton

    • private constructor

      class Foo {
      private:
          Foo();
      }
      
    • a get_xxx() method looks like:

      static Foo *g_foo = NULL;
      Foo *get_foo() {
          if (!g_foo)
              g_foo = create_foo();
          return g_foo;
      }
      

    Factory Method

    • also known as 'Virtual Constructor'
    • delegate class instantiation to subclass
      +----------------+            +-----------------+
      |    Product     |            |    Creator      |
      +----------------+            +-----------------+
              A                     |                 |
              |                     +-----------------+
              |                     |+factoryMethod() |
              |                     +-----------------+
              |                              A
              |                              |
              |                              |
      +-----------------+           +-----------------+
      | ConcreteProduct |<-------<x>| ConcreteCreator |
      +-----------------+           +-----------------+
                                    |                 |
                                    +-----------------+
                                    |+factoryMethod() |
                                    +-----------------+
      

    Observer

    • also known as 'Publish …
  6. "[ARM] CPU registers and modes"

    Registers

    1. r0 ~ r7: general registers
    2. r8 ~ r12: banked registers (in fiq mode)
    3. r13 / sp: stack pointer register
    4. r14 / lr: link register
    5. r15 / pc: program counter register

    CPU modes

    1. (usr) user mode
    2. (sys) system mode
    3. (svc) supervisor mode
    4. (abt) abort mode
    5. (und) undefined mode
    6. (irq) interrupt mode
    7. (fiq) fast interrupt mode …
  7. "[Linux] Speedup Linux clone"

    Background

    In Nov. 2015, kernel.org announced that Fastly(a CDN provider) offered CDN service to provide fast download for Linux kernel releases.

    How to use this feature

    1. Download Linux bundle

      $ wget -c --no-check-certificate https://cdn.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/clone.bundle
      

      In Shanghai …

  8. "[Data Structure] Min Heap"

    Two Charactics of Min Heap

    A Min Heap is represented as a binary tree, this binary tree has two characteristics:

    1. value of a parent node are smaller than which of its child nodes
    2. the binary tree is a complete binary tree
    3. a complete binary tree is defined as:
      • each level …
  9. "[LeetCode][146] LRU Cache"

    class LRUCache(object):
        def __init__(self, capacity):
            self.__capacity = capacity
            self.__dict = {}
            # oldest to youngest
            self.__list = []
    
        def get(self, key):
            if not self.__dict.has_key(key):
                return -1
    
            # move key to the tail of list
            if key != self.__list[-1]:
                self.__list.remove(key)
                self.__list.append(key)
    
            return …
  10. "[LeetCode][155] Min Stack"

    class MinStack(object):
        def __init__(self):
            # stack with entries of (value, cur_min)
            self.l = []
    
        def push(self, x):
            """
            :type x: int
            :rtype: nothing
            """
            prev_min = self.getMin()
            if prev_min == None or prev_min > x:
                cur_min = x
            else:
                cur_min = prev_min
            self.l.append((x, cur_min))
    
        def pop(self):
            """
            :rtype: nothing
            """
            if self.l …
  11. "[LeetCode][134] Gas Station"

    Python

    class Solution(object):
        def __canCompleteCircuit(self, remains, start):
            l = remains[start:] + remains[:start]
            tank = 0
    
            for val in l:
                tank += val
                if tank < 0:
                    return False
            return True
    
        def canCompleteCircuit(self, gas, cost):
            """
            :type gas: List[int]
            :type cost: List[int]
            :rtype: int
            """
            remains = map(lambda a, b : a …
  12. "[LeetCode][125] Valid Palindrome"

    bool isUpperCase(char c)
    {
            return c >= 'A' && c <= 'Z';
    }
    
    bool isLowerCase(char c)
    {
            return c >= 'a' && c <= 'z';
    }
    
    bool isAlpha(char c)
    {
            return isUpperCase(c) || isLowerCase(c);
    }
    
    bool isDigit(char c)
    {
            return c >= '0' && c <= '9';
    }
    
    bool isAlphanumeric(char c)
    {
            return isAlpha(c) || isDigit(c);
    }
    
    bool isCaseInsensitiveEqual(char c1, char …
  13. "[LeetCode][199] Binary Tree Right Side View"

    struct QueueNode {
            struct TreeNode *val;
            struct QueueNode *next;
    };
    
    struct Queue {
            struct QueueNode *front;
            struct QueueNode *rear;
    };
    
    int is_empty(struct Queue *q)
    {
            return !q->front && !q->rear;
    }
    
    struct Queue *queue_create(void)
    {
            struct Queue *q = malloc(sizeof(struct Queue));
    
            q->front = NULL;
            q->rear = NULL;
    
            return q;
    }
    
    void queue_free(struct Queue *q …
  14. "[Performance] Linux Profiling Tools - strace"

    Normal usage

    $ strace gcc hello_world.c
    execve("/usr/bin/gcc", ["gcc", "hello_world.c"], [/* 50 vars */]) = 0
    brk(0)                                  = 0x1c35000
    access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8c4a4d2000
    access("/etc/ld.so.preload", R_OK)      = -1 ENOENT …
  15. "[LeetCode][007] Reverse Integer"

    #define MAX_NUM_OF_DIGITS   10
    #define MAX_VALUE_OF_INT    0x7fffffff
    #define MIN_VALUE_OF_INT    -0x80000000
    
    int reverse(int x)
    {
        int digits[MAX_NUM_OF_DIGITS] = { 0 };
        int sign = x > 0 ? 1 : 0;
        unsigned abs = sign ? x : -x;
        unsigned max = sign ? MAX_VALUE_OF_INT : -MIN_VALUE_OF_INT;
        unsigned result = 0;
        int i = 0;
        int num_digits = 0;
    
        while (abs) {
            digits[i++] = abs % 10;
            abs /= 10 …
  16. "[LeetCode][006] Zigzag Conversion"

    char *convert(char *s, int numRows)
    {
        /* string length */
        int L = strlen(s);
        /* row numbers */
        int R = numRows;
    
        /* parameter check */
        if (L == 0 || R == 1)
            return s;
    
        /* full block numbers */
        /*
         * one 'block' is defined as:
         *     0     
         *     1   5
         *     2 4
         *     3
         */
        int B = L / (2 * R - 2);
        /* remain characters */
        int M …
  17. "[LeetCode][003] Longest Substring Without Repeating Characters"

    /*
     * 1. within range [0, i], [beg, end] is the longest substring, and
     *    [candidate, i] is the possible longer substring.
     * 2. extend range to [0, i + 1], if s[i + 1] can be combined with
     *    [candidate, i] AND if [candidate, i + 1] is longer than [beg, end],
     *    update [beg, end].
     * 3 …
  18. "[LeetCode][001] Two Sum"

    #include <stdio.h>
    #include <stdlib.h>
    
    #define MIN(a, b) ((a) < (b) ? (a) : (b))
    #define MAX(a, b) ((a) > (b) ? (a) : (b))
    
    struct node {
        int index;
        int value;
    };
    
    void list_qsort(struct node **list, int size)
    {
        struct node *anchor = list[0];
        int i = 1;
        int j = size - 1;
        struct node *tmp …
  19. "[LeetCode][002] Add Two Numbers"

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "list.h"
    
    struct ListNode {
    
        int val;
        struct ListNode *next;
    };
    
    /*
     * [in]
     * @nd1: linked list of nodes
     * @nd2: linked list of nodes
     * 
     * [out]
     * none
     *
     * [in/out]
     * @carry(in): carry value of last sum
     * @carry(out): carry value of current sum
     */
    static struct …
  20. "[Dotfile] .tmux.conf"

    # unbind all keys once config is reloaded
    unbind-key -a
    
    # set TERM to screen-256color in tmux
    set -g default-terminal "screen-256color"
    
    # reload config file
    bind r source-file ~/.tmux.conf; display 'config reloaded'
    
    # list current bind keys
    bind ? list-keys
    
    # detach client
    bind d detach-client
    
    # switch client
    bind p switch-client -p
    bind n …
  21. "[Kernel] Kernel and module debugging with gdb"

    What is a loadable module

    • Module entry routine is tagged with __init attribute.
    • __init is to identify code that can be discarded after the the module is loaded so as to not waste any kernel space.
    • Module exit routine is tagged with __exit attribute.
    • __exit is to identify code that …
  22. "[Linux] Module.symvers"

    What is Module.symvers

    • Module.symvers is a plain text file which is generated after kernel building.
    • It records CRC values of all the exported symbols in both vmlinux and modules.

    What Module.symvers is used for

    • Module.symvers is used as a simple ABI consistency check.
    • Before a module …
  23. "[Pthread] Run Two Threads in Turn"

    Pthread Interfaces

    #include <pthread.h>
    int pthread_create(pthread_t *tidp,
                       const pthread_attr_t attr,
               void *(*start_rtn)(void *),
               void *arg);
    int pthread_join(pthread_t *tidp, void **rval_ptr);
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
    int pthread_cond_signal(pthread_cond_t *cond);
    

    Precautions of pthread_cond_wait()

    • pthread_cond_wait() accepts two arguments: 'cond' and …
  24. "[Dotfile] .vimrc"

    " === Vundle Options ===
    set nocompatible
    filetype off
    
    set rtp+=~/.vim/bundle/Vundle.vim
    call vundle#begin()
    " let Vundle manage Vundle
    Plugin 'gmarik/Vundle.vim'
    " plugin from http://vim-scripts.org/vim/scripts.html
    Plugin 'a.vim'
    Plugin 'taglist.vim'
    Plugin 'gtags.vim'
    " plugin from github repo
    Plugin 'godlygeek/tabular'
    Plugin 'plasticboy/vim-markdown …
  25. "[Objective-C] Basic Concepts"

    Property

    Use weak property to avoid strong reference cycle

    • Typical senario: delegate
    +---------------------------------------------------------------------+
    | NSTableView:                       Delegate Object:                 |
    |                          strong                                     |
    |                        --------->                                   |
    | @property id delegate;            @property NSTableView *tableview; |
    |                        <---------                                   |
    |                          strong                                     |
    +---------------------------------------------------------------------+
    
    • Solution: declare 'delegate' as weak property
    +----------------------------------------------------------------------------+
    | NSTableView:                              Delegate Object:                 |
    |                                  weak                                      |
    |                               --------->                                   |
    | @property (weak) id delegate;            @property NSTableView *tableview; |
    |                               <---------                                   |
    |                                 strong                                     |
    +----------------------------------------------------------------------------+
    

    Use object cache to keep weak object alive

    • In …
  26. "[C] A Bug Caused by Misuse of '#if' Macro"

    Bug description

    To fully simplify my situation but also clearly show the key points, I use some dummy code to describe this bug.

    Considering that we want to let our code execute in following logic:

    • If FOO is defined, execute in path A
    • Else, execute in path B

    But to …

  27. "[Performance] Linux Profiling Tools - time"

    Shell built-in time

    We often use time command to measure the executing time of a program. It will print program's real, user and sys time respectively.

    However, our commonly used 'time' is just a shell (bash, zsh) built-in command (same kind as 'cd', 'pwd' and etc). In some use cases …

  28. "[Performance] Linux Profiling Tools - vmstat"

    Run vmstat

    #=> update every 1 second
    $ vmstat 1
    procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
     r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
     15  0   2852 46686812 279456 1401196    0    0     0     0    0    0  0  0 100  0
     16  0   2852 46685192 …
  29. "[Kernel] Linux GPIO Subsystem"

    Kernel GPIO Interface

    bool gpio_is_valid(int number);
     int gpio_request(unsigned gpio, const char *label);
    void gpio_free(unsigned gpio);
     int gpio_direction_input(unsigned gpio);
     int gpio_direction_output(unsigned gpio, int value);
     int gpio_get_value(unsigned gpio);
    void gpio_set_value(unsigned gpio, int value);
     int gpio_export(unsigned gpio, bool direction_may_change);
    void gpio_unexport(unsigned gpio);
     int gpio_to_irq …