Build illumos source code on OmniOS

To build illumos source code on OmniOS, you need to update system and install related tools (Assume you run as root) first:

# pkg update
# pkg install pkg:/developer/illumos-tools

Then clone illumos source code and compile ():

# git clone https://github.com/illumos/illumos-gate.git
# cd illumos-gate
# time ksh93 usr/src/tools/scripts/nightly /opt/onbld/env/omnios-illumos-gate

That’s it!

References:
Building illumos;
Build error of illumos-gate on OmniOS.

Install OmniOS on VirtualBox

Following document to install OmniOS is quite straightforward. I use r151030 version and pick Solaris 11 during selecting Operating Systems on VirtualBox. To use root login through SSH, I need to do following changes:

(1) Set PermitRootLogin‘s value to yes in /etc/ssh/sshd_config file;

(2) Restart SSH service:

# svcadm restart ssh

A fresh OmniOS is born:

Update:

When installing r151032, I found selecing Oracle Solaris 10 10/09 and later (64-bit) can work.

Reference:
Solaris : How to enable ssh login for root user after a fresh install.

 

As a system programming language, C still deserves learning today

C is a system programming language which is old but with “bad” fame: undefined behavior, notorious memory related bugs, etc. Especially with Go and Rust having gone viral right now, C seems already forgotten by people. Nevertheless, IMHO, C is still a thing which is worth for you spending some time on it.

Whether you are are a C novice or a C veteran,I highly recommend you read Modern C if you haven’t read it before. Then you will find C also evolves stealthily and is not as primitive as you think. E.g., C11 has defined standard thread APIs like C++ has done, which makes C more like a “modern” language, not an outdated thing. You may get a new perspective of C from this book.

Regardless if you are a systems language programmer, DevOps, performance engineer or wear other hats, the more you know about the Operating System, the more you can do your job better. Take all prevailing Unix-like Operating Systems as an example, from kernel to command line tools, they are almost implemented in C. To study related source code can make you delve into Operating System internal deeper. E.g., I knew there is a taskset command which can bind specified process of a dedicated CPU, but I wanted to know the magic behind it, so I went through its code. Then I learned 2 things:
a) There is a “/proc/%pid/task” folder which records thread information of process;
b) taskset actually calls sched_setaffinity and sched_getaffinity APIs to attain its goal.

Last but not least, because C is so “low-level”, you can leverage it to write highly performant code to squeeze out CPU when performance is critical in some scenarios.

Although I have listed many reasons which I think you should learn C, you may have sufficient excuses to refuse to dabble into C too. It doesn’t matter. But if you want to give C a shot, firstly you should not be scared of it. There are many ways of writing wrong C code, but you only need to make sure what you write is correct and in defined behavior, that’s all about programming.

First taste of C thread APIs

Since C11, C provides standard thread APIs like what C++ does. It means technically, you should use C‘s standard thread APIs to do multi-thread stuff, not pthread APIs. Below is a simple example:

#include <threads.h>
#include <stdio.h>

int print_thread(void* s)
{
    printf("%s\n", (char*)s);
    thrd_exit(0);
}
int main()
{
    thrd_t tid;
    if (thrd_success != thrd_create(&tid, print_thread, "Hello world"))
    {
        fprintf(stderr, "Create thread error\n");
        return 1;
    }
    thrd_join(tid, NULL);
    return 0;
}

Check thrd_create implementation in glibc:

#include "thrd_priv.h"

int
thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
{
  _Static_assert (sizeof (thr) == sizeof (pthread_t),
          "sizeof (thr) != sizeof (pthread_t)");

  int err_code = __pthread_create_2_1 (thr, ATTR_C11_THREAD,
                       (void* (*) (void*))func, arg);
  return thrd_err_map (err_code);
}

You can see thrd_create just encapsulates __pthread_create_2_1, so you can guess in glibc, the standard C thread APIs are just wrappers of pthreadimplementation. It means you need to link pthread library during compiling. Otherwise you will meet following errors:

main.c:(.text+0x1e): undefined reference to `thrd_exit'
......
main.c:(.text+0x4f): undefined reference to `thrd_create'
/usr/bin/ld: main.c:(.text+0x60): undefined reference to `thrd_join'

P.S., the full code is here.

Access thread information on Dragonfly BSD

On Dragonfly BSD, even it already provides pseudo proc file system, you can’t access thread information like Linux (/proc/$pid/task). You still need to use kvm:

......
kvm_t* kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
......
struct kinfo_proc *proc = kvm_getprocs(
                                kd,
                                KERN_PROC_PID | KERN_PROC_FLAG_LWP,
                                (int)(pid),
                                &cnt);
......
kvm_close(kd); 

According to man:

The number of processes found is returned in the reference parameter cnt. The processes are returned as a contiguous array of kinfo_proc structures.

There is kp_lwp member in kinfo_proc structure which records information of this thread, i.e., LWP. E.g., To print every thread’s ID:

......
printf("Process (%s) has %d threads, and LWP IDs are:\n", argv[1], cnt);
for (int i = 0; i < cnt; i++)
{
    printf("%d\n",  proc[i].kp_lwp.kl_tid);
}
......

For other BSDs, the principle may be similar.

P.S., the full code is here.