view TaskManager/Cell/SpeThreads.cc @ 2022:fac44ad2867d draft

make a sound
author Masataka Kohagura <kohagura@cr.ie.u-ryukyu.ac.jp>
date Wed, 16 Jul 2014 02:50:32 +0900
parents 392c1a2d699d
children
line wrap: on
line source

#include <stdlib.h>
#include "types.h"
#include "SpeThreads.h"
#include "Scheduler.h"


SpeThreads::SpeThreads(int num) : cpu_num(num) {}

SpeThreads::~SpeThreads(void)
{
    memaddr mail = (memaddr)MY_SPE_COMMAND_EXIT;
    int ret;

    for (int i = 0; i < cpu_num; i++) {
        send_mail(i, 1, &mail);
    }

    for (int i = 0; i < cpu_num; i++) {
        pthread_join(threads[i], NULL);
        ret = spe_context_destroy(spe_ctx[i]);
        if (ret) {
            perror("[~SpeThreads] spe_context_destroy");
        }
    }

    spe_image_close(spe_handle);

    delete [] spe_ctx;
    delete [] threads;
    delete [] args;
}

void*
SpeThreads::spe_thread_run(void *arg)
{
    unsigned int entry = SPE_DEFAULT_ENTRY;
    //spe_context_ptr_t ctx = (spe_context_ptr_t)arg;
    thread_arg_t *arg_t = (thread_arg_t *)arg;

    spe_stop_info_t stop_info;
    unsigned long long status;
    
    spe_context_run(arg_t->ctx, &entry, 0, (void*)arg_t->speid, NULL, &stop_info);
    
    status = ((stop_info.result.spe_exit_code & 0xff) << 8)
        | (stop_info.result.spe_signal_code & 0xff);

    switch(stop_info.stop_reason) {
    case SPE_EXIT:	
        break;
    case SPE_STOP_AND_SIGNAL:
        printf("[SPE %d] SPE_STOP_AND_SIGNAL stop_info.result.stop_signal_code=%d\n", arg_t->speid, stop_info.result.spe_signal_code);
        break;
    case SPE_RUNTIME_ERROR:
        printf("[SPE %d] SPE_RUNTIME_ERROR stop_info.result.spe_runtime_error=%d\n", arg_t->speid,  stop_info.result.spe_runtime_error);
        break;
    case SPE_RUNTIME_EXCEPTION:
        printf("[SPE %d] SPE_RUNTIME_EXCEPTION stop_info.result.spe_runtime_exception=%d\n", arg_t->speid,  stop_info.result.spe_runtime_exception);
        break;
    }

    pthread_exit(NULL);
}

void*
SpeThreads::frontend_thread_run(void *arg)
{
    pthread_t thread;
    thread_arg_t *arg_t = (thread_arg_t *)arg;

    pthread_create(&thread, NULL, &spe_thread_run, (void*)arg_t->ctx);

    // mail read の blocking ができれば
    // ここで呼んだ方が早い。

    pthread_exit(NULL);
}

void
SpeThreads::init(void)
{
    spe_handle = spe_image_open(SPE_ELF);

    if (spe_handle == NULL) {
        perror("spe_image_open");
        exit(EXIT_FAILURE);
    }

    spe_ctx = new spe_context_ptr_t[cpu_num];
    threads = new pthread_t[cpu_num];
    args    = new thread_arg_t[cpu_num];

    for (int i = 0; i < cpu_num; i++) {
        args[i].speid = i;
        spe_ctx[i] = spe_context_create(0, NULL);
        spe_program_load(spe_ctx[i], spe_handle);
        args[i].ctx = spe_ctx[i];
    }

    for (int i = 0; i < cpu_num; i++) {
        pthread_create(&threads[i], NULL,
                       &spe_thread_run, (void*)&args[i]);
    }
}

int
SpeThreads::spawn_task(int id, TaskListPtr p) {
    p->cpu = id;
    if (p->dim>0 && id >= SPE_0) {
        int dim_count = (p->x)*(p->y)*(p->z);
        if (cpu_num < dim_count)
            dim_count = cpu_num;
        p->self->flag.dim_count = dim_count;
    }
    send_mail(id ,1,(memaddr*)p);
    return 1;
}

/**
 * SPE からのメールを受信する。
 *
 * @param [speid] SPE ID
 *
 * @return Received 32-bit mailbox messages
 *         if ([ret] < 0) no data read
 */
int
SpeThreads::get_mail(int speid, int count, memaddr *ret)
{   
    // only used in CellTaskManagerImpl (should be removed?) 
    return spe_out_mbox_read(spe_ctx[speid], (unsigned int*)ret, count*(sizeof(memaddr)/sizeof(int)));    
}

int
SpeThreads::has_mail(int speid, int count, memaddr *ret)
{
    /* 
     *  spe_out_mbox_status return only 1, waiting for multiple length
     *  does not work.
     */
    if (spe_out_mbox_status(spe_ctx[speid]) >= 1) {    
        return spe_out_mbox_read(spe_ctx[speid], (unsigned int*)ret, count*(sizeof(memaddr)/sizeof(int)));   
    } else {
        return 0;            
    }
}

/**
 * Inbound Mailbox
 * メール送信 PPE -> SPE
 *
 * なるべく NONBLOCKING なんだけど、
 * Inbound Mailbox キューに空きがないと送信できないので
 * 送信する数だけ空いているか確認してから送る。空いて無い場合は待つ。
 *
 * 結局待つんだよな。しかも ALL_BLOCKING って実は busy wait だったりするし
 *
 * @param [speid] SPE ID
 * @param [data] Send 32-bit mailbox messages
 * @param [num] The number of messages
 */
void
SpeThreads::send_mail(int speid, int num, memaddr *data)
{
    spe_in_mbox_write(spe_ctx[speid], (unsigned int *)data, num*(sizeof(memaddr)/sizeof(int)), SPE_MBOX_ALL_BLOCKING);
}

void
SpeThreads::add_output_tasklist(int command, memaddr buff, int alloc_size)
{
    /*
     * output TaskList が無ければ新しく作る
     * あれば TaskList に allocate した Task を追加
     * command に対応した Task の初期化を実行する
     * SPE に data が書き出し終わった後に PPE 側で初期化
     */
    
}

/* end */