예제 #1
0
/**
 * Set a repeated alarm to execute a callback every interval from start.
 */
BOOL
OSSetPeriodicAlarm(OSAlarm *alarm,
                   OSTime start,
                   OSTime interval,
                   AlarmCallback callback)
{
   internal::acquireIdLock(sAlarmLock, alarm);

   // Set alarm
   alarm->nextFire = start;
   alarm->callback = callback;
   alarm->period = interval;
   alarm->context = nullptr;
   alarm->state = OSAlarmState::Set;

   // Erase from old alarm queue
   if (alarm->alarmQueue) {
      internal::AlarmQueue::erase(alarm->alarmQueue, alarm);
      alarm->alarmQueue = nullptr;
   }

   // Add to this core's alarm queue
   auto core = OSGetCoreId();
   auto queue = sAlarmQueue[core];
   alarm->alarmQueue = queue;
   internal::AlarmQueue::append(queue, alarm);

   // Set the interrupt timer in processor
   // TODO: Store the last set CPU alarm time, and simply check this
   // alarm against that time to make finding the soonest alarm cheaper.
   internal::updateCpuAlarmNoALock();

   internal::releaseIdLock(sAlarmLock, alarm);
   return TRUE;
}
예제 #2
0
/**
 * Set a repeated alarm to execute a callback every interval from start.
 */
BOOL
OSSetPeriodicAlarm(OSAlarm *alarm, OSTime start, OSTime interval, AlarmCallback callback)
{
    ScopedSpinLock lock(gAlarmLock);

    // Set alarm
    alarm->nextFire = start;
    alarm->callback = callback;
    alarm->period = interval;
    alarm->context = nullptr;
    alarm->state = OSAlarmState::Set;

    // Erase from old alarm queue
    if (alarm->alarmQueue) {
        OSEraseFromQueue(static_cast<OSAlarmQueue*>(alarm->alarmQueue), alarm);
        alarm->alarmQueue = nullptr;
    }

    // Add to this core's alarm queue
    auto core = OSGetCoreId();
    auto queue = gAlarmQueue[core];
    alarm->alarmQueue = queue;
    OSAppendQueue(queue, alarm);

    // Set the interrupt timer in processor
    gProcessor.setInterruptTimer(core, coreinit::internal::toTimepoint(alarm->nextFire));
    return TRUE;
}
예제 #3
0
BOOL
OSWaitRendezvousWithTimeout(OSRendezvous *rendezvous, uint32_t coreMask, OSTime timeout)
{
   auto core = OSGetCoreId();
   auto success = FALSE;
   auto endTime = OSGetTime() + timeout;

   // Set our core flag
   rendezvous->core[core].store(1, std::memory_order_release);

   do {
      success = TRUE;

      // Check all core flags
      for (auto i = 0u; i < 3; ++i) {
         if (coreMask & (1 << i)) {
            if (!rendezvous->core[i].load(std::memory_order_acquire)) {
               success = FALSE;
            }
         }
      }

      // Check for timeout
      if (timeout != -1 && OSGetTime() >= endTime) {
         break;
      }
   } while (!success);

   return success;
}
예제 #4
0
파일: main.c 프로젝트: brett19/wut
int
main(int argc, char **argv)
{
   OSReport("Main thread running on core %d", OSGetCoreId());

   // Run thread on core 0
   OSThread *threadCore0 = OSGetDefaultThread(0);

   const char *core0Args[] = {
      "Core 0"
   };

   OSRunThread(threadCore0, CoreEntryPoint, 0, core0Args);

   // Run thread on core 2
   OSThread *threadCore2 = OSGetDefaultThread(2);

   const char *core2Args[] = {
      "Core 2"
   };

   OSRunThread(threadCore2, CoreEntryPoint, 2, core2Args);

   // Wait for threads to return
   int resultCore0 = -1, resultCore2 = -1;
   OSJoinThread(threadCore0, &resultCore0);
   OSJoinThread(threadCore2, &resultCore2);

   OSReport("Core 0 thread returned %d", resultCore0);
   OSReport("Core 2 thread returned %d", resultCore2);
   return 0;
}
예제 #5
0
void
GX2Init(be_val<uint32_t> *attributes)
{
   virtual_ptr<uint32_t> cbPoolBase = nullptr;
   uint32_t cbPoolSize = 0x400000;
   uint32_t cbPoolItemSize = 0x100;
   virtual_ptr<char *> argv = nullptr;
   uint32_t argc = 0;

   // Set main gx2 core
   gMainCoreId = OSGetCoreId();

   // Parse attributes
   while (attributes && *attributes != GX2InitAttrib::End) {
      uint32_t id = *(attributes++);
      uint32_t value = *(attributes++);

      switch (id) {
      case GX2InitAttrib::CommandBufferPoolBase:
         cbPoolBase = make_virtual_ptr<uint32_t>(value);
         break;
      case GX2InitAttrib::CommandBufferPoolSize:
         cbPoolSize = value;
         break;
      case GX2InitAttrib::ArgC:
         argc = value;
         break;
      case GX2InitAttrib::ArgV:
         argv = make_virtual_ptr<char *>(value);
         break;
      }
   }

   // Ensure minimum size
   if (cbPoolSize < 0x2000) {
      cbPoolSize = 0x2000;
   }

   // Allocate command buffer pool
   if (!cbPoolBase) {
      cbPoolBase = reinterpret_cast<uint32_t*>((*pMEMAllocFromDefaultHeapEx)(cbPoolSize, 0x100));
   }

   // Init event handler stuff (vsync, flips, etc)
   gx2::internal::initEvents();

   // Initialise command buffer pools
   gx2::internal::initCommandBufferPool(cbPoolBase, cbPoolSize, cbPoolItemSize);

   // Start our driver!
   gpu::driver::start();

   // Setup default gx2 state
   GX2SetDefaultState();
}
예제 #6
0
/**
 * Run a specific task.
 *
 * The task must belong to a queue.
 * The task must be in the Ready state.
 *
 * \return Returns TRUE if task was run.
 */
BOOL
MPRunTask(virt_ptr<MPTask> task)
{
   auto queue = task->queue;

   if (task->state != MPTaskState::Ready) {
      return FALSE;
   }

   if (!queue
     || queue->state == MPTaskQueueState::Stopping
     || queue->state == MPTaskQueueState::Stopped) {
      return FALSE;
   }

   OSUninterruptibleSpinLock_Acquire(virt_addrof(queue->lock));
   queue->tasksReady--;
   queue->tasksRunning++;
   OSUninterruptibleSpinLock_Release(virt_addrof(queue->lock));

   task->state = MPTaskState::Running;
   task->coreID = OSGetCoreId();

   auto start = OSGetTime();
   task->result = cafe::invoke(cpu::this_core::state(),
                               task->func,
                               task->userArg1,
                               task->userArg2);
   task->duration = OSGetTime() - start;

   task->state = MPTaskState::Finished;

   OSUninterruptibleSpinLock_Acquire(virt_addrof(queue->lock));
   queue->tasksRunning--;
   queue->tasksFinished++;

   if (queue->state == MPTaskQueueState::Stopping && queue->tasksRunning == 0) {
      queue->state = MPTaskQueueState::Stopped;
   }

   if (queue->tasks == queue->tasksFinished) {
      queue->state = MPTaskQueueState::Finished;
   }

   OSUninterruptibleSpinLock_Release(virt_addrof(queue->lock));
   return TRUE;
}
예제 #7
0
/**
 * Wait on a rendezvous with a timeout.
 *
 * This will wait with a timeout until all cores matching coreMask have
 * reached the rendezvous point.
 *
 * \return Returns TRUE on success, FALSE on timeout.
 */
BOOL
OSWaitRendezvousWithTimeout(OSRendezvous *rendezvous,
                            uint32_t coreMask,
                            OSTime timeoutNS)
{
   auto core = OSGetCoreId();
   auto success = FALSE;
   auto endTime = OSGetTime() + internal::nanosToTicks(timeoutNS);

   auto waitCore0 = (coreMask & (1 << 0)) != 0;
   auto waitCore1 = (coreMask & (1 << 1)) != 0;
   auto waitCore2 = (coreMask & (1 << 2)) != 0;

   // Set our core flag
   rendezvous->core[core].store(1, std::memory_order_release);

   do {
      if (waitCore0 && rendezvous->core[0].load(std::memory_order_acquire)) {
         waitCore0 = false;
      }

      if (waitCore1 && rendezvous->core[1].load(std::memory_order_acquire)) {
         waitCore1 = false;
      }

      if (waitCore2 && rendezvous->core[2].load(std::memory_order_acquire)) {
         waitCore2 = false;
      }

      if (!waitCore0 && !waitCore1 && !waitCore2) {
         success = TRUE;
         break;
      }

      if (timeoutNS != -1 && OSGetTime() >= endTime) {
         break;
      }

      // We must manually check for interrupts here, as we are busy-looping.
      //  Note that this is only safe as no locks are held during the wait.
      cpu::this_core::checkInterrupts();
   } while (true);

   return success;
}
예제 #8
0
파일: proc.c 프로젝트: Maschell/wut
void
WHBProcInit()
{
   uint64_t titleID = OSGetTitleID();

   // Homebrew Launcher does not like the standard ProcUI application loop,
   // so instead we disable the home buttom menu and use the home button
   // to trigger an exit.
   if (titleID == HBL_TITLE_ID ||
       titleID == MII_MAKER_JPN_TITLE_ID ||
       titleID == MII_MAKER_USA_TITLE_ID ||
       titleID == MII_MAKER_EUR_TITLE_ID) {
      // Important: OSEnableHomeButtonMenu must come before ProcUIInitEx.
      OSEnableHomeButtonMenu(FALSE);
      sFromHBL = TRUE;
   }

   sMainCore = OSGetCoreId();
   sRunning = TRUE;
   ProcUIInitEx(&procSaveCallback, NULL);
   ProcUIRegisterCallback(PROCUI_CALLBACK_HOME_BUTTON_DENIED, &procHomeButtonDenied, NULL, 100);
}
예제 #9
0
파일: proc.c 프로젝트: Maschell/wut
BOOL
WHBProcIsRunning()
{
   ProcUIStatus status;

   if (sMainCore != OSGetCoreId()) {
      ProcUISubProcessMessages(TRUE);
      return sRunning;
   }

   status = ProcUIProcessMessages(TRUE);
   if (status == PROCUI_STATUS_EXITING) {
      WHBProcStopRunning();
   } else if (status == PROCUI_STATUS_RELEASE_FOREGROUND) {
      ProcUIDrawDoneRelease();
   }

   if (!sRunning) {
      ProcUIShutdown();
   }

   return sRunning;
}
예제 #10
0
OSMessageQueue *
OSGetDefaultAppIOQueue()
{
   return &sAppIo->queues[OSGetCoreId()];
}
예제 #11
0
/**
 * Run N tasks from queue.
 *
 * Does not remove tasks from queue.
 * Can be run from multiple threads at once.
 *
 * Side Effects:
 * - Sets state to Stopped if state is Stopping and tasksRunning reaches 0.
 * - Sets state to Finished if all tasks are finished.
 * - TasksReady -> TasksRunning -> TasksFinished.
 *
 * Returns TRUE if at least 1 task is run.
 */
BOOL
MPRunTasksFromTaskQ(MPTaskQueue *queue,
                    uint32_t tasks)
{
   BOOL result = FALSE;

   while (queue->state == MPTaskQueueState::Ready) {
      uint32_t first, count, available;

      OSUninterruptibleSpinLock_Acquire(&queue->lock);
      available = queue->queueSize - queue->queueIndex;
      count = std::min(available, tasks);
      first = queue->queueIndex;
      tasks -= count;

      queue->tasksReady -= count;
      queue->tasksRunning += count;
      queue->queueIndex += count;
      OSUninterruptibleSpinLock_Release(&queue->lock);

      if (count == 0) {
         // Nothing to run, lets go home!
         break;
      }

      // Result is TRUE if at least 1 task is run
      result = TRUE;

      // Mark all tasks as running
      for (auto i = 0u; i < count; ++i) {
         auto task = queue->queue[first + i];
         task->state = MPTaskState::Running;
         task->coreID = OSGetCoreId();
      }

      // Run all tasks
      for (auto i = 0u; i < count; ++i) {
         auto task = queue->queue[first + i];
         auto start = OSGetTime();
         task->result = task->func(task->userArg1, task->userArg2);
         task->state = MPTaskState::Finished;
         task->duration = OSGetTime() - start;
      }

      OSUninterruptibleSpinLock_Acquire(&queue->lock);
      queue->tasksRunning -= count;
      queue->tasksFinished += count;

      if (queue->state == MPTaskQueueState::Stopping && queue->tasksRunning == 0) {
         queue->state = MPTaskQueueState::Stopped;
      }

      if (queue->tasks == queue->tasksFinished) {
         queue->state = MPTaskQueueState::Finished;
      }

      OSUninterruptibleSpinLock_Release(&queue->lock);
   }

   return result;
}
예제 #12
0
void _start()
{
	asm(
		"lis %r1, 0x1ab5 ;"
		"ori %r1, %r1, 0xd138 ;"
	);
	unsigned int coreinit_handle, gx2_handle;
	OSDynLoad_Acquire("coreinit", &coreinit_handle);
	OSDynLoad_Acquire("gx2", &gx2_handle);
	//OS Memory functions
	void*(*memset)(void * dest, unsigned int value, unsigned int bytes);
	void*(*OSAllocFromSystem)(unsigned int size, int align);
	void(*OSFreeToSystem)(void *ptr);
	//IM functions
	int(*IM_Open)();
	int(*IM_Close)(int fd);
	int(*IM_SetDeviceState)(int fd, void *mem, int state, int a, int b);

	//OS Memory functions
	OSDynLoad_FindExport(coreinit_handle, 0, "memset", &memset);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSAllocFromSystem", &OSAllocFromSystem);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSFreeToSystem", &OSFreeToSystem);
	//IM functions
	OSDynLoad_FindExport(coreinit_handle, 0, "IM_Open", &IM_Open);
	OSDynLoad_FindExport(coreinit_handle, 0, "IM_Close", &IM_Close);
	OSDynLoad_FindExport(coreinit_handle, 0, "IM_SetDeviceState", &IM_SetDeviceState);
	//Restart system to get lib access
	int fd = IM_Open();
	void *mem = OSAllocFromSystem(0x100, 64);
	memset(mem, 0, 0x100);
	//set restart flag to force quit browser
	IM_SetDeviceState(fd, mem, 3, 0, 0); 
	IM_Close(fd);
	OSFreeToSystem(mem);
	//wait a bit for browser end
	unsigned int t1 = 0x1FFFFFFF;
	while(t1--) ;

	/* Get the framebuffer of the TV or DRC */
	void(*GX2SwapScanBuffers)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapScanBuffers", &GX2SwapScanBuffers);
	unsigned char *abuseFunc = (unsigned char*)GX2SwapScanBuffers;
	unsigned short f_hi = *(unsigned short*)(abuseFunc+0x12);
	unsigned short f_lo = *(unsigned short*)(abuseFunc+0x16);
	unsigned int gx2settingBase = (((f_lo & 0x8000) ? (f_hi-1) : f_hi) << 16) | f_lo;
	unsigned int args[2];
	args[0] = *((unsigned int*)(gx2settingBase + 0x304));
	args[1] = *((unsigned int*)(gx2settingBase + 0x304 + 0x20));
	int(*OSGetCoreId)();
	OSDynLoad_FindExport(coreinit_handle, 0, "OSGetCoreId", &OSGetCoreId);
	void(*OSTestThreadCancel)();
	OSDynLoad_FindExport(coreinit_handle, 0, "OSTestThreadCancel", &OSTestThreadCancel);
	void(*GX2Shutdown)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2Shutdown", &GX2Shutdown);
	int(*GX2GetMainCoreId)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2GetMainCoreId", &GX2GetMainCoreId);

	/* Prepare for our own death */
	void*(*OSGetCurrentThread)();
	OSDynLoad_FindExport(coreinit_handle, 0, "OSGetCurrentThread", &OSGetCurrentThread);
	void *myBorkedThread = OSGetCurrentThread();
	int (*OSSuspendThread)(void *thread);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSSuspendThread", &OSSuspendThread);

	/* Prepare for thread startups */
	int (*OSCreateThread)(void *thread, void *entry, int argc, void *args, unsigned int stack, unsigned int stack_size, int priority, unsigned short attr);
	int (*OSResumeThread)(void *thread);
	int (*OSIsThreadTerminated)(void *thread);

	OSDynLoad_FindExport(coreinit_handle, 0, "OSCreateThread", &OSCreateThread);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSResumeThread", &OSResumeThread);
	OSDynLoad_FindExport(coreinit_handle, 0, "OSIsThreadTerminated", &OSIsThreadTerminated);

	/* Allocate a stack for the thread */
	unsigned int stack = (unsigned int) OSAllocFromSystem(0x1000, 0x10);
	stack += 0x1000;
	/* Create the thread */
	void *thread = OSAllocFromSystem(OSTHREAD_SIZE, 8);
	
	if(OSGetCoreId() != GX2GetMainCoreId()) //needed for access without crashing
	{
		int ret = OSCreateThread(thread, GX2Shutdown, 0, (void*)0, stack, 0x1000, 0, 0x10 | (1<<GX2GetMainCoreId()));
		if (ret == 0)
			OSFatal("Failed to create thread");
		/* Schedule it for execution */
		OSResumeThread(thread);
		while(OSIsThreadTerminated(thread) == 0) ;
	}
	else //same core, easy
		GX2Shutdown();

	//current thread is broken, switch to a working one in core 1
	int ret = OSCreateThread(thread, myGXthread, 2, args, stack, 0x1000, 0, 0xA);
	if (ret == 0)
		OSFatal("Failed to create thread");

	/* Schedule it for execution */
	OSResumeThread(thread);
	/* SO UGLY but it works magically */
	while(1) ;
	//would be better but again, crashes 5.3.2
	//OSSuspendThread(myBorkedThread);
	//OSFatal("I am still not dead!");
}
예제 #13
0
void myGXthread(int argc, int *argv)
{
	if(argc != 2) OSFatal("GX Thread did not start proper!");
	unsigned int *tv_fb = (unsigned int*)argv[0];
	unsigned int *drc_fb = (unsigned int*)argv[1];
	unsigned int coreinit_handle, gx2_handle;
	OSDynLoad_Acquire("coreinit", &coreinit_handle);
	OSDynLoad_Acquire("gx2", &gx2_handle);

	void(*GX2Init)(void *args);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2Init", &GX2Init);
	GX2Init((void*)0);

	int(*OSGetCoreId)();
	OSDynLoad_FindExport(coreinit_handle, 0, "OSGetCoreId", &OSGetCoreId);
	void(*GX2SwapScanBuffers)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapScanBuffers", &GX2SwapScanBuffers);
	void(*GX2Shutdown)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2Shutdown", &GX2Shutdown);
	int(*GX2GetMainCoreId)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2GetMainCoreId", &GX2GetMainCoreId);
	if(OSGetCoreId() != GX2GetMainCoreId()) OSFatal("GX Not switched!");

	void(*GX2DrawDone)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2DrawDone", &GX2DrawDone);
	void(*GX2Flush)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2Flush", &GX2Flush);
	//void(*GX2SwapScanBuffers)();
	//OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapScanBuffers", &GX2SwapScanBuffers);
	void(*GX2WaitForVsync)();
	OSDynLoad_FindExport(gx2_handle, 0, "GX2WaitForVsync", &GX2WaitForVsync);
	//Make sure buffer is usable for GX
	void(*GX2Invalidate)(unsigned int flags,void *buffer,unsigned int size);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2Invalidate", &GX2Invalidate);
	GX2Invalidate(0x40,tv_fb,(1280*720*4)*2);
	GX2Invalidate(0x40,drc_fb,(854*480*4)*2);
	//set it!
	int(*GX2SetTVBuffer)(void *buffer,unsigned int size,unsigned int flag1,unsigned int flag2,unsigned int flag3);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2SetTVBuffer", &GX2SetTVBuffer);
	int(*GX2SetDRCBuffer)(void *buffer,unsigned int size,unsigned int flag1,unsigned int flag2,unsigned int flag3);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2SetDRCBuffer", &GX2SetDRCBuffer);
	GX2SetTVBuffer(tv_fb,(1280*720*4)*2,3,0x1A,2); //test gradient demo setup for show
	GX2SetDRCBuffer(drc_fb,(854*480*4)*2,1,0x1A,2); //will look broken, no color buffer setup yet
	/* Draw is far from complete */
	/*void(*GX2DrawEx)(int type, int count, int start, int instances);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2DrawEx", &GX2DrawEx);
	void(*GX2SetAttribBuffer)(int index, int size, int vtxStride, void *buf);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2SetAttribBuffer", &GX2SetAttribBuffer);
	float myclearer[8] =
	{
		0.0f,  0.0f,
		1.0f,  0.0f,
		0.0f,  1.0f,
		1.0f,  1.0f
	};
	GX2Invalidate(0x40, myclearer, sizeof(myclearer));*/

	GX2ColorBuffer myCBuf;
	setupColorBuffer(&myCBuf, gx2_handle);

	void(*GX2ClearColor)(GX2ColorBuffer *buffer, float r, float g, float b, float a);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2ClearColor", &GX2ClearColor);

	void(*GX2SwapBuffers)(GX2ColorBuffer *buffer);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2SwapBuffers", &GX2SwapBuffers);

	void(*GX2CopyColorBufferToScanBuffer)(GX2ColorBuffer *buffer, unsigned int target);
	OSDynLoad_FindExport(gx2_handle, 0, "GX2CopyColorBufferToScanBuffer", &GX2CopyColorBufferToScanBuffer);

	float val = 1;
	float valInc = -0.005;
	val += valInc;
	while(val < 1)
	{
		val += valInc;
		//GX2SetAttribBuffer(0,sizeof(mybuf),8,mybuf);
		//GX2DrawEx(6,4,0,1);
		GX2ClearColor(&myCBuf, val, val, val, 1);
		GX2Invalidate(0x40, myCBuf.surface.imagePtr,myCBuf.surface.imageSize);
		GX2DrawDone();
		GX2Flush();
		GX2CopyColorBufferToScanBuffer(&myCBuf,1);
		GX2SwapScanBuffers();
		GX2Flush();
		GX2WaitForVsync();
		if(val <= 0) valInc = 0.005;
	}
	//clear for browser (needed?)
	GX2Shutdown();

	void(*_Exit)();
	OSDynLoad_FindExport(coreinit_handle, 0, "_Exit", &_Exit);
	_Exit();
}
예제 #14
0
void LCDealloc(void * addr)
{
   uint32_t coreId = OSGetCoreId();
   gLcHeaps[coreId]->free(addr);
}
예제 #15
0
void * LCAlloc(uint32_t size)
{
   uint32_t coreId = OSGetCoreId();
   return gLcHeaps[coreId]->alloc(size, 512);
}