int main (void) { int thread_id[nr_t]; pthread_attr_t attr; pthread_t pts[nr_t]; spe_context_ptr_t ctx[nr_t]; unsigned int value; int cnt; /* Use small thread stacks to speed up writing out core file. */ pthread_attr_init (&attr); pthread_attr_setstacksize (&attr, 2*PTHREAD_STACK_MIN); for (cnt = 0; cnt < nr_t; cnt++) { ctx[cnt] = spe_context_create (0, NULL); thread_id[cnt] = pthread_create (&pts[cnt], &attr, &spe_thread, &ctx[cnt]); } pthread_attr_destroy (&attr); for (cnt = 0; cnt < nr_t; cnt++) spe_out_intr_mbox_read (ctx[cnt], &value, 1, SPE_MBOX_ALL_BLOCKING); abort (); }
unsigned int sws_receive_message(yuvscaler_t *arg) { unsigned int message; struct yuvscaler_s * arg_ptr; arg_ptr=(struct yuvscaler_s *) arg; int retries = 3; while(retries) { if(spe_event_wait(arg->spe_event_yuvscaler, &arg->event, 1, -1) <= 0 || !(arg->event.events & SPE_EVENT_OUT_INTR_MBOX)) { retries--; } else { break; } } if(retries == 0) { perror("Failed to recive result from spe"); } spe_out_intr_mbox_read(arg_ptr->ctx,&message,1,SPE_MBOX_ANY_NONBLOCKING); return message; }
int main (void) { pthread_t pts; spe_context_ptr_t ctx; unsigned int value; unsigned int pid; ctx = spe_context_create (0, NULL); pthread_create (&pts, NULL, &spe_thread, &ctx); /* Wait until the SPU thread is running. */ spe_out_intr_mbox_read (ctx, &value, 1, SPE_MBOX_ALL_BLOCKING); pid = fork (); if (pid == 0) { /* This is the child. Just exit immediately. */ exit (0); } else { /* This is the parent. Wait for the child to exit. */ waitpid (pid, NULL, 0); } /* Tell SPU to continue. */ spe_in_mbox_write (ctx, &value, 1, SPE_MBOX_ALL_BLOCKING); pthread_join (pts, NULL); spe_context_destroy (ctx); return 0; }
extern "C" void runMigratedMethod(SpuThreadData * spu_data, int chosenSpu, int runMethodSignal) { unsigned int signalData, err; // signal spu to run method signalData = (unsigned int) runMethodSignal; if (spe_in_mbox_write(spu_data->spus[chosenSpu].ctx, &signalData, 1, SPE_MBOX_ANY_NONBLOCKING) < 0) { perror("Failed while trying to signal method details to Cell SPU"); exit(1); } // check we get an ACK back if (spe_out_intr_mbox_read(spu_data->spus[chosenSpu].ctx, &signalData, 1, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Failed reading SPU mailbox while awaiting SPU method invocation"); exit(1); } // if method run was not acked if (signalData != ACK) { // read error signal spe_out_mbox_read(spu_data->spus[chosenSpu].ctx, &err, 1); fprintf(stderr, "SPU did not ACK method run signal, signaled 0x%x, returned error no. 0x%x\n", signalData, err); exit(1); } }
/* Register the event handlers for each context */ void waitForSpus(SpuThreadData * spu_data) { int i, no_spus; pid_t pid; no_spus = spu_data->no_spu_threads; pid = getpid(); // used to order reorder spu's by physical id unsigned int phys_ids [no_spus]; for (i=0; i<no_spus; i++) { unsigned int message_data [2]; unsigned long long spu_id; if (spe_out_intr_mbox_read(spu_data->spus[i].ctx, message_data, 2, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Failed reading SPU mailbox while awaiting SPU boot"); exit(1); } spu_id = ((unsigned long long)message_data[0]) << 32 | message_data[1]; // find out the physical spu number for each thread phys_ids[i] = getPhysID(spu_id, (unsigned long long)spu_data->gang, pid); spu_data->spus[i].phys_id = phys_ids[i]; if (spe_in_mbox_write(spu_data->spus[i].ctx, &(phys_ids[i]), 1, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Failed writing phys_id to SPU mailbox while SPU was booting"); exit(1); } } // order ctxs and threads by phys id SpuData * new_spus = (SpuData *) malloc(sizeof(SpuData) * no_spus); for (i=0; i<no_spus; i++) { int j, current_idx; unsigned int current; current = 0xefffffff; current_idx = 0; for (j=0; j<no_spus; j++) { if (phys_ids[j] < current) { current = phys_ids[j]; current_idx = j; } } memcpy(&(new_spus[i]), &(spu_data->spus[current_idx]), sizeof(SpuData)); phys_ids[current_idx] = 0xefffffff; } free(spu_data->spus); spu_data->spus = new_spus; }
extern "C" int sysVirtualSubArchProcessorBind(VM_Address procObj, int procID) { unsigned int signal[2]; // TODO - do some checking here SpuData spu = global_spu_data->spus[procID]; signal[0] = SET_PROCESSOR_REG; signal[1] = (unsigned int) procObj; // tell spu runtime its processor object if (spe_in_mbox_write(spu.ctx, signal, 2, SPE_MBOX_ANY_NONBLOCKING) < 0) { perror("Failed while trying to signal method details to Cell SPU"); exit(1); } // wait for ACK from SPU if (spe_out_intr_mbox_read(spu.ctx, signal, 1, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Faied reading SPU mailbox while awaiting SPU boot"); exit(1); } if (signal[0] != ACK) { spe_out_mbox_read(spu.ctx, signal, 1); fprintf(stderr, "SPU did not ACK setProcessor, returned error no. 0x%x\n", signal[0]); exit(1); } return 0; }
void waitForRuntime(SpuThreadData * spu_data) { int i; unsigned int message_data[2]; for (i=0; i<spu_data->no_spu_threads; i++) { if (spe_out_intr_mbox_read(spu_data->spus[i].ctx, message_data, 2, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Failed reading SPU mailbox while awaiting SPU boot"); exit(1); } if ((message_data[0] == JAVA_VM_STARTED) && message_data[1] == spu_data->spus[i].phys_id) { // printf("SPU %i Java VM started\n", spu_data->spus[i].phys_id); } else { printf("message_data[0] - 0x%x, message_data[1] - 0x%x\n",message_data[0], message_data[1]); fprintf(stderr, "SPU %i did not succecfully transition to Java VM\n", spu_data->spus[i].phys_id); exit(1); } } }
extern "C" int supportSPU(SpuThreadData * spu_data, SpuJavaThreadData * thread, int chosenSpu) { unsigned int cmdSignal; char stop = 0; while (!stop) { if (spe_out_intr_mbox_read(spu_data->spus[chosenSpu].ctx, &cmdSignal, 1, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Failed reading while waiting for a command signal from SPU"); exit(1); } switch (cmdSignal) { case TRAP_MESSAGE: handleTrap(chosenSpu); break; case FAKE_TRAP_MESSAGE: printf("Fake Trap Called from SPU\n"); break; case FAKE_TRAP_MESSAGE_STR: handleFakeTrap(chosenSpu); break; case FAKE_TRAP_MESSAGE_INT: handleFakeTrapInt(chosenSpu); break; case CONSOLE_WRITE_CHAR: handleConsoleWrite(chosenSpu); break; case CONSOLE_WRITE_INT: case CONSOLE_WRITE_INT_BOTH: case CONSOLE_WRITE_INT_HEX: handleConsoleIntWrite(chosenSpu, cmdSignal); break; case CONSOLE_WRITE_LONG: case CONSOLE_WRITE_LONG_BOTH: case CONSOLE_WRITE_LONG_HEX: handleConsoleLongWrite(chosenSpu, cmdSignal); break; case CONSOLE_WRITE_DOUBLE: handleConsoleDoubleWrite(chosenSpu); break; case RETURN_VALUE_V: stop = 1; break; case RETURN_VALUE_I: case RETURN_VALUE_F: case RETURN_VALUE_R: if (spe_out_mbox_read(global_spu_data->spus[chosenSpu].ctx, &(thread->retVal[0]), 1) < 0) { perror("Error reading return value from SPU migrated method\n"); exit(1); } stop = 1; break; case RETURN_VALUE_L_UPPER: case RETURN_VALUE_D_UPPER: if (spe_out_mbox_read(global_spu_data->spus[chosenSpu].ctx, &(thread->retVal[0]), 1) < 0) { perror("Error reading return value from SPU migrated method\n"); exit(1); } break; case RETURN_VALUE_L_LOWER: case RETURN_VALUE_D_LOWER: if (spe_out_mbox_read(global_spu_data->spus[chosenSpu].ctx, &(thread->retVal[1]), 1) < 0) { perror("Error reading return value from SPU migrated method\n"); exit(1); } stop = 1; break; default: { unsigned int err = 0; fprintf(stderr, "Unknown signal recieved from SPU: 0x%x", cmdSignal); spe_out_mbox_read(spu_data->spus[chosenSpu].ctx, &err, 1); fprintf(stderr, "Error signal was: 0x%x\n", err); exit(1); } } } return 0; }
/* Prepare SPU for migration of a thread */ void prepareMigration(SpuThreadData * spu_data, int chosenSpu, int methodClassTocOffset, int methodSubArchOffset, VM_Address paramsStart, int paramsLength) { int i; unsigned int methodSignal[3]; unsigned int paramSignal[2]; unsigned int retSignal; unsigned int * params = (unsigned int *) paramsStart; reloadJtoc(spu_data, chosenSpu); loadTocTables(spu_data, chosenSpu); // TODO - see if we can defer this waiting (note offset required for method load) waitForProxyload(spu_data, chosenSpu); methodSignal[0] = LOAD_STATIC_METHOD; methodSignal[1] = (unsigned int) methodClassTocOffset; methodSignal[2] = (unsigned int) methodSubArchOffset; if (spe_in_mbox_write(spu_data->spus[chosenSpu].ctx, methodSignal, 3, SPE_MBOX_ANY_NONBLOCKING) < 0) { perror("Failed while trying to signal method details to Cell SPU"); exit(1); } // wait for ACK from SPU if (spe_out_intr_mbox_read(spu_data->spus[chosenSpu].ctx, &retSignal, 1, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Failed reading SPU mailbox while awaiting SPU boot"); exit(1); } if (retSignal != ACK) { spe_out_mbox_read(spu_data->spus[chosenSpu].ctx, &retSignal, 1); fprintf(stderr, "SPU did not ACK method load signal, returned error no. 0x%x\n", retSignal); exit(1); } // load params for (i=0; i<paramsLength; i++) { // TODO - Double params paramSignal[0] = LOAD_WORD_PARAM; paramSignal[1] = params[paramsLength - (i + 1)]; if (spe_in_mbox_write(spu_data->spus[chosenSpu].ctx, paramSignal, 2, SPE_MBOX_ANY_NONBLOCKING) < 0) { perror("Failed while trying to signal method details to Cell SPU"); exit(1); } // wait for ACK from SPU if (spe_out_intr_mbox_read(spu_data->spus[chosenSpu].ctx, &retSignal, 1, SPE_MBOX_ALL_BLOCKING) < 0) { perror("Failed reading SPU mailbox while awaiting SPU boot"); exit(1); } if (retSignal != ACK) { spe_out_mbox_read(spu_data->spus[chosenSpu].ctx, &retSignal, 1); fprintf(stderr, "SPU did not ACK method para load signal, returned error no. 0x%x\n", retSignal); exit(1); } } }
void quilt_orizontal(Picture *pout, int dim_bucata_height, int dim_bucata_width, int nbucati_height, int nbucati_width, int dim_fasie_height, int dim_fasie_width, int npatches, int ncandidati, int in_width) { int height = pout->Height(); int off_candidat = -1, off_candidat_min = -1; int min_dif = -1, curr_dif = -1; #ifndef CELL for (int i = 0; i < npatches; i++) { min_dif = 1 << 30; // Pentru fiecare petic nou adaugat, exista ncandidati petice // ce candideaza pentru ocuparea pozitiei for (int j = 0; j < ncandidati; j++) { off_candidat = rand() % (in_width - dim_fasie_width); curr_dif = orizontal_dif(pout, off_candidat, in_width + (i - 1) * dim_bucata_width, dim_fasie_width, dim_bucata_width, height); if (min_dif> curr_dif) { min_dif = curr_dif; off_candidat_min = off_candidat; } } orizontal_netezire(pout, i, in_width, height, dim_fasie_width, dim_bucata_width, off_candidat_min); } #else for (int i = 0; i < npatches; i++) { min_dif = 1 << 30; // Pentru fiecare petic nou adaugat, exista ncandidati petice // ce candideaza pentru ocuparea pozitiei for (int j = 0; j < ncandidati; j++) { off_candidat = rand() % (in_width - dim_fasie_width); curr_dif = orizontal_dif(pout, off_candidat, in_width + (i - 1) * dim_bucata_width, dim_fasie_width, dim_bucata_width, height); } // Astept de la toate raspunsul for (int i = 0; i < spu_threads; i++) { adr_value[0] = (unsigned int) 2; if (spe_in_mbox_write(spes[i], adr_value, 1, SPE_MBOX_ANY_NONBLOCKING) < 0) { perror("ERROR, writing messages to spe failed\n"); } } unsigned int buffer_candidat_off, buffer_candidat_val, off_candidat_min = -1, val_candidat_min = 1 << 30; for (i = 0; i < NO_SPU; ++i) { nevents = spe_event_wait(event_handler, &event_received, 1, -1); if (event_received.events & SPE_EVENT_OUT_INTR_MBOX) { while (spe_out_intr_mbox_status(event_received.spe) < 1) ; spe_out_intr_mbox_read(event_received.spe, &buffer_candidat_val, 1, SPE_MBOX_ANY_BLOCKING); while (spe_out_intr_mbox_status(event_received.spe) < 1) ; spe_out_intr_mbox_read(event_received.spe, &buffer_candidat_off, 1, SPE_MBOX_ANY_BLOCKING); } if (buffer_candidat_val < val_candidat_min) { val_candidat_min = buffer_candidat_val; off_candidat_min = buffer_candidat_off; } orizontal_netezire(pout, i, in_width, height, dim_fasie_width, dim_bucata_width, off_candidat_min); } } #endif }