マルチスレッドの実装

Mona には syscall_mthread_create() と syscall_mthread_join() というスレッド作成用のシステムコールがありますが、引数に関数ポインターを取るため C++ で使うのは結構面倒くさいです。というわけでJava風のスレッドクラスで隠蔽してみました。

#include <monapi.h>
#include <monapi/messages.h>
static dword parent_tid = 0;
// ================================================================================
/** スレッドインターフェース */
class Runnable {
protected:
    bool running;
public:
    Runnable() {
        this->running = true;
    }
    virtual void run() = 0;
    virtual void stop() {
        this->running = false;
    }
};
// ================================================================================
/** Monaスレッド */
static void ExecRun() {
    MonAPI::Message::send(parent_tid, MSG_SERVER_START_OK);
    dword child_tid = syscall_get_tid();
    for (MessageInfo info;;) {
        if (MonAPI::Message::receive(&info) != 0) continue;
        if (info.header == MSG_SERVER_START_OK) {
            Runnable* runnable = (Runnable*)info.arg1;
            runnable->run();
            break;
        }
    }
    syscall_kill_thread(child_tid);
}
/** スレッドクラス */
class Thread {
private:
    Runnable* runnable;
public:
    Thread(Runnable* runnable) {
        this->runnable = runnable;
    }
    void start() {
        dword thread_id = syscall_mthread_create((dword)ExecRun);
        syscall_mthread_join(thread_id);
        // MSG_SERVER_START_OKが返ってくるのを待つ
        MessageInfo msg, src;
        src.header = MSG_SERVER_START_OK;
        MonAPI::Message::receive(&msg, &src, MonAPI::Message::equalsHeader);
        dword child_tid = msg.from;
        // Runnable::run() を呼ばせる
        MonAPI::Message::send(child_tid, MSG_SERVER_START_OK, (dword)runnable);
    }
};
// ================================================================================
/** ユーザスレッド(1) */
class MyThead1 : public Runnable {
public:
    virtual void run() {
        while (this->running) {
            sleep(500);
            printf("hoge,");
        }
    }
};
// ================================================================================
/** ユーザスレッド(2) */
class MyThead2 : public Runnable {
public:
    virtual void run() {
        while (this->running) {
            sleep(1000);
            printf("fuga,");
        }
    }
};
// ================================================================================
/** エントリーポイント */
int MonaMain(List<char*>* argv) {
    parent_tid = syscall_get_tid();
    // スレッドを2個起動する
    MyThead1* myThead1 = new MyThead1();
    Thread* thread1 = new Thread(myThead1);
    thread1->start();
    MyThead2* myThead2 = new MyThead2();
    Thread* thread2 = new Thread(myThead2);
    thread2->start();
    // メッセージループ
    for (MessageInfo info;;) {
        if (MonAPI::Message::receive(&info) != 0) continue;
    }
    return 0;
}

マルチスレッドは考慮しなければいけないことが非常に多いです。
以下の本をお勧めします。結城さんの本は説明がすごくわかりやすいです。