Ejemplo n.º 1
0
uint8 HitachiDSP::rom_read(unsigned addr) {
  if(co_active() == cpu.thread) {
    if(state.i == State::Idle) return cartridge.rom.read(addr);
    if((addr & 0x40ffe0) == 0x00ffe0) return regs.vector[addr & 0x1f];
    return cpu.regs.mdr;
  }
  if(co_active() == hitachidsp.thread) {
    return cartridge.rom.read(addr);
  }
  return cpu.regs.mdr;
}
Ejemplo n.º 2
0
int main() {
  printf("context-switching timing test\n\n");
  time_t start, end;
  int i, t1, t2;

  start = clock();
  for(thread::counter = 0, i = 0; i < Iterations; i++) {
    sub_timingtest();
  }
  end = clock();

  t1 = (int)difftime(end, start);
  printf("%2.3f seconds per  50 million subroutine calls (%d iterations)\n", (float)t1 / CLOCKS_PER_SEC, thread::counter);

  thread::x = co_active();
  thread::y = co_create(65536, co_timingtest);

  start = clock();
  for(thread::counter = 0, i = 0; i < Iterations; i++) {
    co_switch(thread::y);
  }
  end = clock();

  co_delete(thread::y);

  t2 = (int)difftime(end, start);
  printf("%2.3f seconds per 100 million co_switch  calls (%d iterations)\n", (float)t2 / CLOCKS_PER_SEC, thread::counter);

  printf("co_switch skew = %fx\n\n", (double)t2 / (double)t1);
  return 0;
}
Ejemplo n.º 3
0
extern "C" dllexport bool __cdecl DllInit(const char* ipcname)
{
	printf("NEW INSTANCE: %08X\n", &s_EmulationControl);

	char pipename[256];
	char eventname[256];
	sprintf(pipename, "\\\\.\\Pipe\\%s",ipcname);
	sprintf(eventname, "%s-event", ipcname);

	printf("pipe: %s\n",pipename);
	printf("event: %s\n",eventname);

	hPipe = CreateFile(pipename, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

	if(hPipe == INVALID_HANDLE_VALUE)
		return false;

	hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, ipcname);
	if(hMapFile == INVALID_HANDLE_VALUE)
		return false;

	hMapFilePtr = MapViewOfFile(hMapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);

	//make a coroutine thread to run the emulation in. we'll switch back to this thread when communicating with the frontend
	co_control = co_active();
	co_emu = co_create(65536*sizeof(void*),emuthread);

	running = true;
	printf("running\n");

	DWORD tid;
	CreateThread(nullptr, 0, &ThreadProc, nullptr, 0, &tid);

	return true;
}
void async_worker_enter(async_worker_t *const worker) {
	assert(worker);
	assert(!worker->work);
	worker->work = co_active();
	async_call(enter, worker);
	// Now on worker thread
}
int async_mutex_trylock(async_mutex_t *const mutex) {
	assert(mutex && "Mutex must not be null");
	cothread_t const thread = co_active();
	if(mutex->active.thread && thread != mutex->active.thread) return -1;
	async_mutex_lock(mutex);
	return 0;
}
Ejemplo n.º 6
0
uint8 HitachiDSP::rom_read(unsigned addr) {
  if(co_active() == hitachidsp.thread || regs.halt) {
    addr = bus.mirror(addr, rom.size());
  //if(Roms == 2 && mmio.r1f52 == 1 && addr >= (bit::round(rom.size()) >> 1)) return 0x00;
    return rom.read(addr);
  }
  if((addr & 0x40ffe0) == 0x00ffe0) return mmio.vector[addr & 0x1f];
  return cpu.regs.mdr;
}
static work(async_worker_t *const worker) {
	worker->main = co_active();
	for(;;) {
		uv_sem_wait(&worker->sem);
		if(!worker->work) break;
		co_switch(worker->work);
		uv_async_send(work->async);
	}
}
Ejemplo n.º 8
0
static void async_start(void) {
	async_t thread[1];
	thread->fiber = co_active();
	thread->flags = 0;
	active = thread;
	void (*const func)(void *) = arg_func;
	void *arg = arg_arg;
	func(arg);
	async_call(co_delete, thread->fiber);
}
Ejemplo n.º 9
0
void retro_init (void){ 

#ifndef M16B
    	enum retro_pixel_format fmt =RETRO_PIXEL_FORMAT_XRGB8888;
#else
    	enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
#endif

		const char *system_dir = NULL;
   
		if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir) && system_dir)
		{
			// if defined, use the system directory			
			retro_system_directory=system_dir;		
		}		   
		
		const char *content_dir = NULL;
   
		if (environ_cb(RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY, &content_dir) && content_dir)
		{
			// if defined, use the system directory			
			retro_content_directory=content_dir;		
		}			
		
		const char *save_dir = NULL;
   
		if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &save_dir) && save_dir)
		{
			// If save directory is defined use it, otherwise use system directory
			retro_save_directory = *save_dir ? save_dir : retro_system_directory;      
		}
		else
		{
			// make retro_save_directory the same in case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY is not implemented by the frontend
			retro_save_directory=retro_system_directory;
		}
		
		printf("Retro SYSTEM_DIRECTORY %s\n",retro_system_directory);
		printf("Retro SAVE_DIRECTORY %s\n",retro_save_directory);
		printf("Retro CONTENT_DIRECTORY %s\n",retro_content_directory);


    	if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
    	{
    		fprintf(stderr, "RGB pixel format is not supported.\n");
    		exit(0);
    	}

	if(!emuThread && !mainThread)
    	{
        	mainThread = co_active();
        	emuThread = co_create(65536*sizeof(void*), retro_wrap_emulator);
    	}

}
Ejemplo n.º 10
0
int async_init(void) {
	int rc = uv_loop_init(async_loop);
	if(rc < 0) return rc;
	master->fiber = co_active();
	master->flags = 0;
	active = master;
	async_main = master;
	trampoline = co_create(STACK_DEFAULT, trampoline_fn);
	if(!trampoline) return UV_ENOMEM;
	return 0;
}
Ejemplo n.º 11
0
void waittorun(void)
{
  // i suppose it would be possible to switch off the main thread
  // without ever having made a context for it.  then it would never
  // be able to activate again.
  coprivate *this = (coprivate *) co_active();
  WaitForSingleObject(this->sem, INFINITE);
  if (this->wantdie)
  {
    CloseHandle(this->sem);
	ExitThread(0);
  }
}
Ejemplo n.º 12
0
cothread_t co_create(unsigned int size, void (*entry_)(void)) {
  uintptr_t entry = (uintptr_t)entry_;
  uint32_t* t = 0;

  /* be sure main thread was successfully allocated */
  if(co_active()) {
    size += state_size + above_stack + stack_align;
    t = co_create_(size, entry);
  }

  if(t) {
    uintptr_t sp;
    int shift;

    /* save current registers into new thread, so that any special ones will have proper values when thread is begun */
    CO_SWAP_ASM(t, t);

    #if LIBCO_PPCDESC
    entry = (uintptr_t)*(void**)entry;  /* get real address */
    #endif

    /* put stack near end of block, and align */
    sp = (uintptr_t)t + size - above_stack;
    sp -= sp % stack_align;

    /* on PPC32, we save and restore GPRs as 32 bits. for PPC64, we
       save and restore them as 64 bits, regardless of the size the ABI
       uses. so, we manually write pointers at the proper size. we always
       save and restore at the same address, and since PPC is big-endian,
       we must put the low byte first on PPC32. */

    /* if uintptr_t is 32 bits, >>32 is undefined behavior,
       so we do two shifts and don't have to care how many bits uintptr_t is. */
    #if LIBCO_PPC64
    shift = 16;
    #else
    shift = 0;
    #endif

    /* set up so entry will be called on next swap */
    t[ 8] = (uint32_t)(entry >> shift >> shift);
    t[ 9] = (uint32_t)entry;

    t[10] = (uint32_t)(sp >> shift >> shift); 
    t[11] = (uint32_t)sp;
  }

  return t;
}
Ejemplo n.º 13
0
struct mk_http_thread *mk_http_thread_create(int type,
                                             struct mk_vhost_handler *handler,
                                             struct mk_http_session *session,
                                             struct mk_http_request *request,
                                             int n_params,
                                             struct mk_list *params)
{
    size_t stack_size;
    struct mk_thread *th = NULL;
    struct mk_http_thread *mth;
    struct mk_sched_worker *sched;

    sched = mk_sched_get_thread_conf();
    if (!sched) {
        return NULL;
    }

    th = mk_thread_new(sizeof(struct mk_http_thread), NULL);
    if (!th) {
        return NULL;
    }

    mth = (struct mk_http_thread *) MK_THREAD_DATA(th);
    if (!mth) {
        return NULL;
    }

    mth->session = session;
    mth->request = request;
    mth->parent  = th;
    mth->close   = MK_FALSE;
    request->thread = mth;
    mk_list_add(&mth->_head, &sched->threads);

    th->caller = co_active();
    th->callee = co_create(MK_THREAD_STACK_SIZE,
                           thread_cb_init_vars, &stack_size);

#ifdef MK_HAVE_VALGRIND
    th->valgrind_stack_id = VALGRIND_STACK_REGISTER(th->callee,
                                                    ((char *)th->callee) + stack_size);
#endif

    /* Workaround for makecontext() */
    thread_params_set(th, type, handler, session, request, n_params, params);

    return mth;
}
static bool_t getPage(EFSRepoRef const repo, HTTPConnectionRef const conn, HTTPMethod const method, strarg_t const URI) {
	if(HTTP_GET != method) return false;
	size_t pathlen = prefix("/", URI);
	if(!pathlen) return false;
	if(!pathterm(URI, (size_t)pathlen)) return false;
	EFSSessionRef const session = auth(repo, conn, method, URI+pathlen);
	if(!session) {
		HTTPConnectionSendStatus(conn, 403);
		return true;
	}

	// TODO: Parse querystring `q` parameter
	EFSFilterRef const filter = EFSFilterCreate(EFSTypeFilter);
	EFSFilterAddStringArg(filter, "text/html; charset=utf-8");

	EFSFileInfo *const files = EFSSessionCreateFileInfoList(session, filter, RESULTS_MAX);

	HTTPConnectionWriteResponse(conn, 200, "OK");
	HTTPConnectionWriteHeader(conn, "Content-Type", "text/html; charset=utf-8");
	HTTPConnectionWriteHeader(conn, "Transfer-Encoding", "chunked");
	HTTPConnectionBeginBody(conn);

	// TODO: Page header

	uv_fs_t req = { .data = co_active(); }
	for(index_t i = 0; i < files->count; ++i) {
		uv_fs_open(loop, &req, path, O_RDONLY, 0400, async_fs_cb);
		co_switch(yield);
		uv_fs_req_cleanup(&req);
		uv_file const file = req.result;
		if(file < 0) continue;
		HTTPConnectionWriteChunkLength(conn, files->items[i].size);
		HTTPConnectionWriteFile(conn, file);
		uv_fs_close(loop, &req, file, async_fs_cb);
		co_switch(yield);
		uv_fs_req_cleanup(&req);
		HTTPConnectionWrite(conn, "\r\n", 2);
	}

	// TODO: Page trailer

	HTTPConnectionWriteChunkLength(conn, 0);
	HTTPConnectionWrite(conn, "\r\n", 2);
	HTTPConnectionEnd(conn);

	EFSFileInfoListFree(files);
	return true;
}
void async_mutex_unlock(async_mutex_t *const mutex) {
	assert(mutex && "Mutex must not be null");
	cothread_t const thread = co_active();
	assert(mutex->active.thread && "Leaving empty mutex");
	assert(thread == mutex->active.thread && "Leaving someone else's mutex");
	assert(mutex->depth > 0 && "Mutex recursion depth going negative");
	if(--mutex->depth) return;
	if(!mutex->active.next) return;
	list_entry *const next = mutex->active.next;
	if(!next->next) mutex->tail = &mutex->active;
	mutex->active.thread = next->thread;
	mutex->active.next = next->next;
	mutex->depth = 1;
	async_wakeup(next->thread);
	// Set everything up ahead of time so we aren't dependent on whether the wakeup is synchronous or not.
}
Ejemplo n.º 16
0
void WritePipeBuffer(const void* buf, int len)
{
	if(co_active() != co_control)
	{
		printf("WARNING: WRITING FROM NON-CONTROL THREAD\n");
	}
	//static FILE* outf = NULL;
	//if(!outf) outf = fopen("c:\\trace.bin","wb"); fwrite(buf,1,len,outf); fflush(outf);

	if(bufio)
	{
		wbuf->Write(buf,len);
		return;
	}

	DWORD bytesWritten;
	BOOL result = WriteFile(hPipe, buf, len, &bytesWritten, NULL);
	if(!result || bytesWritten != len)
		exit(1);
}
Ejemplo n.º 17
0
void Emu_init()
{
#ifdef RETRO_AND
   //you can change this after in core option if device support to setup a 832x576 res 
   retrow=640; 
   retroh=480;
   MOUSEMODE=1;
#endif

   update_variables();

   memset(Key_Sate,0,512);
   memset(Key_Sate2,0,512);

   if(!emuThread && !mainThread)
   {
      mainThread = co_active();
      emuThread = co_create(65536*sizeof(void*), retro_wrap_emulator);
   }

}
Ejemplo n.º 18
0
void retro_init (void){ 

#ifndef M16B
    	enum retro_pixel_format fmt =RETRO_PIXEL_FORMAT_XRGB8888;
#else
    	enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
#endif

    	if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
    	{
    		fprintf(stderr, "RGB pixel format is not supported.\n");
    		exit(0);
    	}

	if(!emuThread && !mainThread)
    	{
        	mainThread = co_active();
        	emuThread = co_create(65536*sizeof(void*), retro_wrap_emulator);
    	}

}
void async_mutex_lock(async_mutex_t *const mutex) {
	assert(mutex && "Mutex must not be null");
	cothread_t const thread = co_active();
	if(!mutex->active.thread) {
		mutex->active = thread;
	} else if(thread == mutex->active.thread) {
		mutex->depth++;
	} else {
		assert(mutex->tail && "Mutex has no tail");
		assert(mutex->tail->thread && "Mutex tail has no thread");
		list_entry us = {
			.thread = thread,
			.next = NULL,
		};
		mutex->tail->next = &us;
		mutex->tail = &us;
		co_switch(yield);
		assert(thread == mutex->active.thread && "Mutex wrong thread obtained lock");
		// TODO
	}
}
Ejemplo n.º 20
0
int main() {
  printf("cothread parameterized function example\n\n");

  thread[0] = co_active();
  thread[1] = co_create(65536, co_entrypoint);
  thread[2] = co_create(65536, co_entrypoint);

//use specialized co_switch(cothread_t, int, int) for initial co_switch call
  co_switch(thread[1], 1, 2);
  co_switch(thread[2], 4, 8);

//after first call, entry point arguments have been initialized, standard
//co_switch(cothread_t) can be used from now on
  co_switch(thread[2]);
  co_switch(thread[1]);

  printf("\ndone\n");
#if defined(_MSC_VER) || defined(__DJGPP__)
  getch();
#endif
  return 0;
}
Ejemplo n.º 21
0
int main( void )
{
	int i, n;
	
	printf( "Thread test\n" );
	print_libco_opts();
	
	threads [0] = co_active();
	threads [1] = co_create( stack_size, entry );
	assert( threads [1] );
	for ( n = 0; n < iter; n++ )
	{
		/*
		if ( !(n & (n - 1)) )
			printf( "%d\n", n );*/
		
		for ( i = 1; i < max_threads; i++ )
			if ( threads [i] )
				co_switch( threads [i] );
	}
	
	{
		unsigned all = 0;
		for ( i = 0; i < 16; i++ )
			all ^= shared [i];
		
		if ( all != final_data )
		{
			printf( "0x%08X\n", all );
			printf( "Incorrect CRC\n" );
			return EXIT_FAILURE;
		}
	}
	
	printf( "Passed\n\n" );
	return 0;
}
Ejemplo n.º 22
0
void Scheduler::init() {
  clock.cpu_freq = snes.region() == SNES::NTSC
                 ? snes.config.cpu.ntsc_clock_rate
                 : snes.config.cpu.pal_clock_rate;
  clock.smp_freq = snes.region() == SNES::NTSC
                 ? snes.config.smp.ntsc_clock_rate
                 : snes.config.smp.pal_clock_rate;

  clock.active = THREAD_CPU;
  clock.cpuppu = 0;
  clock.cpusmp = 0;
  clock.smpdsp = 0;

  if(thread_cpu) co_delete(thread_cpu);
  if(thread_smp) co_delete(thread_smp);
  if(thread_ppu) co_delete(thread_ppu);
  if(thread_dsp) co_delete(thread_dsp);

  thread_snes = co_active();
  thread_cpu  = co_create(65536 * sizeof(void*), threadentry_cpu);
  thread_smp  = co_create(65536 * sizeof(void*), threadentry_smp);
  thread_ppu  = co_create(65536 * sizeof(void*), threadentry_ppu);
  thread_dsp  = co_create(65536 * sizeof(void*), threadentry_dsp);
}
	if(sqflags & SQLITE_OPEN_READWRITE) uvflags |= O_RDWR;
	if(sqflags & SQLITE_OPEN_READONLY) uvflags |= O_RDONLY;
	uv_fs_t req = { .data = co_active() };
	uv_fs_open(vfs->pAppData->loop, &req, path, uvflags, 0600, fs_cb);
	co_switch(vfs->pAppData->yield);
	int const result = req.result;
	uv_fs_req_cleanup(&req);
	if(result < 0) return SQLITE_CANTOPEN;
	file->methods = &io_methods;
	file->file = result;
	file->thread = vfs->pAppData;
	file->lockLevel = SQLITE_LOCK_NONE;
	return SQLITE_OK;
}
static int squvco_delete(sqlite3_vfs *const vfs, char const *const path, int const syncDir) {
	uv_fs_t req = { .data = co_active() };
	uv_fs_unlink(vfs->pAppData->loop, &req, path, fs_cb);
	co_switch(vs->pAppData->yield);
	int const unlinkresult = req.result;
	uv_fs_req_cleanup(&req);
	if(ENOENT == unlinkresult) return SQLITE_OK;
	if(unlinkresult < 0) return SQLITE_IOERR_DELETE;
	if(syncDir) {
		str_t dirname[MAXPATHNAME+1];
		sqlite3_snprintf(MAXPATHNAME+1, dirname, "%s", path);
		index_t i = strlen(dirname);
		for(; i > 1 && '/' != dir[i]; ++i);
		dirname[i] = '\0';

		uv_fs_open(vfs->pAppData->loop, &req, dirname, fs_cb);
		co_switch(vfs->pAppData->yield);
void async_worker_leave(async_worker_t *const worker) {
	assert(worker);
	assert(co_active() == worker->work);
	co_switch(worker->main);
	// Now on original thread
}
Ejemplo n.º 25
0
void co_switch(cothread_t handle)
{
   cothread_t co_previous_handle = co_active();
   co_switch_arm(co_active_handle = handle, co_previous_handle);
}
int async_mutex_check(async_mutex_t *const mutex) {
	assert(mutex && "Mutex must not be null");
	return co_active() == mutex->active.thread;
}
Ejemplo n.º 27
0
static void run( jmp_buf jb, int depth )
{
	unsigned local [16];
	memcpy( local, shared, sizeof local );
	
	if ( depth > max_depth )
		max_depth = depth;
	
	while ( 1 )
	{
		co_switch( threads [0] );
		
		switch ( rnd() & 7 )
		{
		case 0:
			if ( depth > 0 )
			{
				if ( rnd() & 1 )
					#if STRESS_EXCEPTIONS
						throw 0;
					#else
						longjmp( jb, 1 );
					#endif
				goto ret;
			}
			break;
		
		case 1:
			if ( depth < 50 )
			{
				#if STRESS_EXCEPTIONS
				{
					try {
						run( jb, depth + 1 );
					}
					catch ( ... )
					{ }
				}
				#else
				{
					jmp_buf jb2;
					if ( !setjmp( jb2 ) )
						run( jb2, depth + 1 );
				}
				#endif
			}
			break;
		
		case 2: {
			int i;
			for ( i = 0; i < max_threads; i++ )
			{
				if ( !threads [i] )
				{
					threads [i] = co_create( stack_size, entry );
					assert( threads [i] );
					break;
				}
			}
			break;
		}
		
		case 3:
		{
			int i = rnd() & (max_threads - 1);
			if ( i > 0 && threads [i] && threads [i] != co_active() )
			{
				co_delete( threads [i] );
				threads [i] = 0;
			}
			break;
		}
		
		case 4:
		case 5:
		case 6:
		case 7: {
			int n;
			for ( n = 10; n--; )
			{
				unsigned r;
				r = rnd(); local [r & 15]  += rnd();
				r = rnd(); shared [r & 15] += rnd();
				r = rnd(); local [r & 15]  ^= shared [rnd() & 15];
				r = rnd(); shared [r & 15] ^= local [rnd() & 15];
			}
			break;
		}
		
		}
		
		{
			int i = rnd() & (max_threads - 1);
			if ( threads [i] && threads [i] != co_active() )
				co_switch( threads [i] );
		}
	}
ret:;
}
Ejemplo n.º 28
0
void Scheduler::enter() {
  host_thread = co_active();
  co_switch(thread);
}
Ejemplo n.º 29
0
void Scheduler::reset() {
  host_thread = co_active();
  thread = cpu.thread;
  sync = SynchronizeMode::None;
  exit_reason = ExitReason::UnknownEvent;
}
Ejemplo n.º 30
0
void Scheduler::exit(ExitReason reason) {
  exit_reason = reason;
  thread = co_active();
  co_switch(host_thread);
}