pte_osResult pte_osInit(void) { pte_osResult result; psl1ghtThreadData *pThreadData; /* Allocate and initialize TLS support */ result = pteTlsGlobalInit(PSL1GHT_MAX_TLS); if (result == PTE_OS_OK) { /* Allocate a key that we use to store control information (e.g. cancellation semaphore) per thread */ result = pteTlsAlloc(&threadDataKey); if (result == PTE_OS_OK) { /* Initialize the structure used to emulate TLS for * non-POSIX threads */ globalTls = pteTlsThreadInit(); /* Also create a "thread data" structure for a single non-POSIX thread. */ /* Allocate some memory for our per-thread control data. We use this for: * 1. Entry point and parameters for the user thread's main function. * 2. Semaphore used for thread cancellation. */ pThreadData = (psl1ghtThreadData *) malloc(sizeof(psl1ghtThreadData)); if (pThreadData == NULL) { result = PTE_OS_NO_RESOURCES; } else { sys_sem_attr_t attr; /* Save a pointer to our per-thread control data as a TLS value */ pteTlsSetValue(globalTls, threadDataKey, pThreadData); /* Create a semaphore used to cancel threads */ attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL; attr.attr_pshared = SYS_SEM_ATTR_PSHARED; attr.key = 0; attr.flags = 0; snprintf(attr.name, sizeof(attr.name), "cnclGlob"); if (sysSemCreate(&pThreadData->cancelSem, &attr, 0, 255) != 0) { free (pThreadData); result = PTE_OS_NO_RESOURCES; } result = PTE_OS_OK; } } } return result; }
/* Create a counting semaphore */ SDL_sem * SDL_CreateSemaphore(Uint32 initial_value) { SDL_sem *sem; sys_sem_attr_t attr; SDL_zero( attr); attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL; attr.attr_pshared = SYS_SEM_ATTR_PSHARED; sem = (SDL_sem *) SDL_malloc(sizeof(*sem)); if (sem) { sysSemCreate( &sem->id, &attr, initial_value, 32 * 1024); } else { SDL_OutOfMemory(); } return (sem); }
pte_osResult pte_osSemaphoreCreate(int initialValue, pte_osSemaphoreHandle *pHandle) { static int semCtr = 0; sys_sem_attr_t attr; if (semCtr++ > MAX_PSL1GHT_UID) { semCtr = 0; } attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL; attr.attr_pshared = SYS_SEM_ATTR_PSHARED; attr.key = 0; attr.flags = 0; snprintf(attr.name,sizeof(attr.name),"sem%d",semCtr); sysSemCreate(pHandle, &attr, initialValue, SEM_VALUE_MAX); return PTE_OS_OK; }
/* init event handler */ void eventInitialization ( eventData *edata ) { dbgprintf ( "initializing" ) ; /* initialize variables */ edata->menu = 1 ; edata->exitapp = 1 ; edata->xmbopen = 0 ; /* initialize semaphore attributes */ edata->sem_attr.key = 0x03 ; edata->sem_attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL ; edata->sem_attr.attr_pshared = SYS_SEM_ATTR_PSHARED ; /* initialize mutex attributes */ edata->mutex_attr.key = 0x03 ; edata->mutex_attr.attr_protocol = SYS_MUTEX_PROTOCOL_FIFO ; edata->mutex_attr.attr_pshared = SYS_MUTEX_ATTR_PSHARED ; edata->mutex_attr.attr_recursive = SYS_MUTEX_ATTR_RECURSIVE ; edata->mutex_attr.attr_adaptive = SYS_MUTEX_ATTR_ADAPTIVE ; /* initialize condition attributes */ edata->cond_attr.key = 0x03 ; edata->cond_attr.attr_pshared = SYS_COND_ATTR_PSHARED ; /* create semaphore */ sysSemCreate ( &edata->sem, &edata->sem_attr, 1, SEM_CONSUMERS ) ; /* create mutex */ sysMutexCreate ( &edata->mutex, &edata->mutex_attr ) ; /* create cond */ sysCondCreate ( &edata->cond, edata->mutex, &edata->cond_attr ) ; /* register eventHandler */ sysUtilRegisterCallback ( SYSUTIL_EVENT_SLOT0, eventHandler, edata ) ; dbgprintf ( "initialized" ) ; }
/* initialize controller */ void padInitialization (padBtnData *pdata ) { dbgprintf ( "initializing" ) ; /* initialize state variables */ pdata->btn = 0 ; pdata->now = 0 ; pdata->last = 0 ; /* initialize semaphore attributes */ pdata->sem_attr.key = PAD_KEY ; pdata->sem_attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL ; pdata->sem_attr.attr_pshared = SYS_SEM_ATTR_PSHARED ; /* initialize mutex attributes */ pdata->mutex_attr.key = PAD_KEY ; pdata->mutex_attr.attr_protocol = SYS_MUTEX_PROTOCOL_FIFO ; pdata->mutex_attr.attr_pshared = SYS_MUTEX_ATTR_PSHARED ; pdata->mutex_attr.attr_recursive = SYS_MUTEX_ATTR_RECURSIVE ; pdata->mutex_attr.attr_adaptive = SYS_MUTEX_ATTR_ADAPTIVE ; /* initialize condition attributes */ pdata->cond_attr.key = PAD_KEY ; pdata->cond_attr.attr_pshared = SYS_COND_ATTR_PSHARED ; /* create semaphore */ sysSemCreate ( &pdata->sem, &pdata->sem_attr, 1, SEM_CONSUMERS ) ; /* create mutex */ sysMutexCreate ( &pdata->mutex, &pdata->mutex_attr ) ; /* create cond */ sysCondCreate ( &pdata->cond, pdata->mutex, &pdata->cond_attr ) ; ioPadInit ( 7 ) ; dbgprintf ( "initialized" ) ; }
pte_osResult pte_osThreadCreate(pte_osThreadEntryPoint entryPoint, int stackSize, int initialPriority, void *argv, pte_osThreadHandle* ppte_osThreadHandle) { char threadName[28]; static int threadNum = 1; int psl1ghtAttr; void *pTls; sys_ppu_thread_t threadId; pte_osResult result; psl1ghtThreadData *pThreadData; sys_sem_attr_t sem_attr; s32 ret; if (threadNum++ > MAX_PSL1GHT_UID) { threadNum = 0; } /* Make sure that the stack we're going to allocate is big enough */ if (stackSize < DEFAULT_STACK_SIZE_BYTES) { stackSize = DEFAULT_STACK_SIZE_BYTES; } /* Allocate TLS structure for this thread. */ pTls = pteTlsThreadInit(); if (pTls == NULL) { PSL1GHT_DEBUG("pteTlsThreadInit: PTE_OS_NO_RESOURCES\n"); result = PTE_OS_NO_RESOURCES; goto FAIL0; } /* Allocate some memory for our per-thread control data. We use this for: * 1. Entry point and parameters for the user thread's main function. * 2. Semaphore used for thread cancellation. */ pThreadData = (psl1ghtThreadData *) malloc(sizeof(psl1ghtThreadData)); if (pThreadData == NULL) { pteTlsThreadDestroy(pTls); PSL1GHT_DEBUG("malloc(psl1ghtThreadData): PTE_OS_NO_RESOURCES\n"); result = PTE_OS_NO_RESOURCES; goto FAIL0; } /* Save a pointer to our per-thread control data as a TLS value */ pteTlsSetValue(pTls, threadDataKey, pThreadData); pThreadData->entryPoint = entryPoint; pThreadData->argv = argv; /* Create a semaphore used to cancel threads */ sem_attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL; sem_attr.attr_pshared = SYS_SEM_ATTR_PSHARED; sem_attr.key = 0; sem_attr.flags = 0; snprintf(sem_attr.name, sizeof(sem_attr.name), "cncl%04d", threadNum); ret = sysSemCreate(&pThreadData->cancelSem, &sem_attr, 0, 255); if (ret == 0) { /* In order to emulate TLS functionality, we append the address of the TLS structure that we * allocated above to the thread's name. To set or get TLS values for this thread, the user * needs to get the name of the thread from the OS and then parse the name to extract * a pointer to the TLS structure. */ snprintf(threadName, sizeof(threadName), "pthread%04d__%x", threadNum, (unsigned int) ((u64)pTls)); // FIXME: joinable or not ? psl1ghtAttr = 0; pThreadData->priority = initialPriority; pThreadData->ended = 0; // printf("%s %p %d %d %d\n",threadName, psl1ghtStubThreadEntry, initialPriority, stackSize, psl1ghtAttr); ret = sysThreadCreate(&threadId, psl1ghtStubThreadEntry, pThreadData, OS_MAX_PRIO, stackSize, psl1ghtAttr, threadName); } if (ret == 0x80010004) { free(pThreadData); pteTlsThreadDestroy(pTls); PSL1GHT_DEBUG("sceKernelCreateThread: PTE_OS_NO_RESOURCES\n"); result = PTE_OS_NO_RESOURCES; } else if (ret != 0) { free(pThreadData); pteTlsThreadDestroy(pTls); PSL1GHT_DEBUG("sceKernelCreateThread: PTE_OS_GENERAL_FAILURE\n"); result = PTE_OS_GENERAL_FAILURE; } else { *ppte_osThreadHandle = threadId; result = PTE_OS_OK; } FAIL0: return result; }