git: How to revert a file to a specific commit

git checkout COMMIT_HASH file/to/revert

Will bring the file/to/revert file to the state in COMMIT_HASH commit.

git: Completely revert the last commit

git reset --hard HEAD~1

will completely revert the last commit (i.e., everything from this commit will disappear).

git: How to checkout a specific commit/version to a new branch

git checkout -b branch--new commit-hash

will checkout the commit-hash commit in a new branch called branch-new.

git: How to push a new branch to a remote repository

git push -u REMOTE BRANCH_NAME

This will also create an association between the local and the remote branch, so you can afterwards just issue git push.

The simplest linked list implementation in C

I recently needed to develop a way to perform pseudo-random memory accesses in a C program, in order to fool the hardware prefetchers. Without going into any details, my solution was to represent some continuous memory as a linked list with random next pointers.

Naturally, the simplest list that can be developed has nodes that do not contain any other elements apart from the next pointers that link the nodes together. In C, this can be easily done with a structure similar to the following:

struct node
{
  struct node* next;
}

However, one can leverage the flexibility of C to even avoid using the node structure: you are allowed to cast some memory to any type you like. For instance, you can use 8 bytes as an integer(uint64_t) , or as a pointer to an integer (uint64_t*).

Doing so, we can develop, what I believe is, the simplest linked list possible.
The code that generates a random list is the following:

static void
create_rand_list(volatile uint64_t* list, size_t n)
{
  srand(time(NULL));
  uint8_t* used = calloc(n, sizeof(uint8_t));
  assert (used != NULL);
 
  size_t idx = 0;
  size_t used_num = 0;
  while (used_num < n - 1)
    {
      used[idx] = 1;
      used_num++;
 
      size_t nxt;
      do
        {
          nxt = rand() % n;
        }
      while (used[nxt]);
 
      list[idx] = (uint64_t) (list + nxt);
      idx = nxt;
    }
 
  list[idx] = 0; 		/* NULL pointer in the last element */
 
  free(used);
}

The “magic” happens when we set list[idx] = (uint64_t) (list + nxt), so we set the “next” pointer for the location idx.
What is even more interesting is how we can now parse and get the size of the list:

static void
list_parse(volatile uint64_t* l)
{
  while (*l != 0)
    {
      l = (uint64_t*) *l;
    }
}
 
static size_t
list_size(volatile uint64_t* l)
{
  size_t s = 1;
  while (*l != 0)
    {
      l = (uint64_t*) *l;
      s++;
    }
  return s;
}

Pretty slick, right? 🙂

git: How to merge two commits into one

git rebase -i

and then pick the one you want to keep and squash the other

Everything You Always Wanted to Know about Synchronization but Were Afraid to Ask

It’s just one day before traveling to the US to present “Everything You Always Wanted to Know about Synchronization but Were Afraid to Ask” in the the 24th ACM Symposium on Operating Systems Principles (SOSP). I am really glad that I will have the opportunity to share the knowledge we collected in over a year of hard work. You can get a copy of the paper here.

This publication is about understanding the low-level details of the hardware (e.g., the cache-coherence protocol) and how they affect synchronization (and sharing of data in general) in software. If you want to better understand your hardware, to optimize your system/application, or to understand why something scales or does not scale, I believe you will be interested in reading the paper.

We also published the software we developed to perform this study as the SSYNC synchronization suite (SSYNC stands for Simple Synchronization). If the information in the paper is not sufficient for your needs, or if you have a hardware platform that is not very similar with the ones we used in the paper, then you can use the tools and libraries of SSYNC to evaluate your own platform.

SSYNC is available at http://lpd.epfl.ch/site/ssync and contains:

  • ccbench: a tool for measuring the latencies of the hardware cache-coherence protocol
  • libslock: a library with cross-platform implementations of various locking algorithms
  • libssmp: a message passing library optimized for x86, SPARC, and Tilera platforms
  • TM2C: the first software Transactional Memory for Many-Cores

I hope you will enjoy reading the paper 🙂

git: How to see the changes of a file for a commit

git show [commit] -- FILE