1) Implemented new IPI sending/receiving mechanism. Now we have our
own IRQ line for IPIs. On the sending part, we don't use Linux
low-level functions anymore since they use spinlock + linked-list. We
use customized point-to-point lock-free ring buffer to avoid locks and
achieve minimal cache migration between cores. Changed acaps to use
new mechanism.

2) New thread creation method. To create a new thread, a component
needs to allocate a local thread entry (which includes a function
pointer and a data pointer), and pass the index of the entry to
scheduler. The scheduler then passes the index to the newly created
thread, which will use the index to access the entry function and
data. The benefit of this approach is, the scheduler won't be able to
control the entry points of client components (and thus not able to
cause fault in them). The behavior of new threads in a component is
defined by that component only.

3) In the scheduler, new created thread will upcall into the
destination component directly, instead of upcalling into scheduler
first.