static int effective_num_processors(void) { // JJG: To keep mamehub completely deterministic, force the # of processors to 1. return 1; int physprocs = osd_get_num_processors(); // osd_num_processors == 0 for 'auto' if (osd_num_processors > 0) { return MIN(4 * physprocs, osd_num_processors); } else { int numprocs = 0; // if the OSDPROCESSORS environment variable is set, use that value if valid // note that we permit more than the real number of processors for testing const char *procsoverride = osd_getenv(ENV_PROCESSORS); if (procsoverride != NULL && sscanf(procsoverride, "%d", &numprocs) == 1 && numprocs > 0) return MIN(4 * physprocs, numprocs); // otherwise, return the info from the system return physprocs; } }
static UINT32 effective_cpu_mask(int index) { char *s; char buf[5]; UINT32 mask = 0xFFFF; s = osd_getenv(SDLENV_CPUMASKS); if (s != NULL && strcmp(s,"none")) { if (!strcmp(s,"auto")) { if (index<2) mask = 0x01; /* main thread and io threads on cpu #0 */ else mask = (1 << (((index - 1) % (osd_get_num_processors() - 1)) + 1)); } else { if (strlen(s) % 4 != 0 || strlen(s) < (index+1)*4) { fprintf(stderr,"Invalid cpu mask @index %d: %s\n", index, s); } else { memcpy(buf,s+4*index,4); buf[4] = 0; if (sscanf(buf, "%04x", &mask) != 1) fprintf(stderr,"Invalid cpu mask element %d: %s\n", index, buf); } } } return mask; }
static int effective_num_processors(void) { char *procsoverride; int numprocs = 0; int physprocs = osd_num_processors(); if (sdl_num_processors > 0) return MIN(4 * physprocs, sdl_num_processors); else { // if the OSDPROCESSORS environment variable is set, use that value if valid procsoverride = osd_getenv(SDLENV_PROCESSORS); if (procsoverride != NULL && sscanf(procsoverride, "%d", &numprocs) == 1 && numprocs > 0) return MIN(4 * physprocs, numprocs); // otherwise, return the info from the system return physprocs; } }
int osd_setenv(const char *name, const char *value, int overwrite) { char *buf; int result; if (!overwrite) { if (osd_getenv(name) != NULL) return 0; } buf = (char *) osd_malloc_array(strlen(name)+strlen(value)+2); sprintf(buf, "%s=%s", name, value); result = putenv(buf); /* will be referenced by environment * Therefore it is not freed here */ return result; }
static int effective_num_processors(void) { int physprocs = osd_get_num_processors(); // osd_num_processors == 0 for 'auto' if (osd_num_processors > 0) { return std::min(4 * physprocs, osd_num_processors); } else { int numprocs = 0; // if the OSDPROCESSORS environment variable is set, use that value if valid // note that we permit more than the real number of processors for testing const char *procsoverride = osd_getenv(ENV_PROCESSORS); if (procsoverride != nullptr && sscanf(procsoverride, "%d", &numprocs) == 1 && numprocs > 0) return std::min(4 * physprocs, numprocs); // otherwise, return the info from the system return physprocs; } }
file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize) { UINT32 access; const char *src; char *dst; #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) || defined(SDLMAME_HAIKU) struct stat st; #else struct stat64 st; #endif char *tmpstr, *envstr; int i, j; file_error filerr = FILERR_NONE; tmpstr = NULL; // allocate a file object, plus space for the converted filename *file = (osd_file *) osd_malloc_array(sizeof(**file) + sizeof(char) * strlen(path)); if (*file == NULL) { filerr = FILERR_OUT_OF_MEMORY; goto error; } if (sdl_check_socket_path(path)) { (*file)->type = SDLFILE_SOCKET; filerr = sdl_open_socket(path, openflags, file, filesize); goto error; } if (strlen(sdlfile_ptty_identifier) > 0 && strncmp(path, sdlfile_ptty_identifier, strlen(sdlfile_ptty_identifier)) == 0) { (*file)->type = SDLFILE_PTTY; filerr = sdl_open_ptty(path, openflags, file, filesize); goto error; } (*file)->type = SDLFILE_FILE; // convert the path into something compatible dst = (*file)->filename; for (src = path; *src != 0; src++) *dst++ = (*src == INVPATHSEPCH) ? PATHSEPCH : *src; *dst++ = 0; // select the file open modes if (openflags & OPEN_FLAG_WRITE) { access = (openflags & OPEN_FLAG_READ) ? O_RDWR : O_WRONLY; access |= (openflags & OPEN_FLAG_CREATE) ? (O_CREAT | O_TRUNC) : 0; } else if (openflags & OPEN_FLAG_READ) { access = O_RDONLY; } else { filerr = FILERR_INVALID_ACCESS; goto error; } tmpstr = (char *) osd_malloc_array(strlen((*file)->filename)+1); strcpy(tmpstr, (*file)->filename); // does path start with an environment variable? if (tmpstr[0] == '$') { envstr = (char *) osd_malloc_array(strlen(tmpstr)+1); strcpy(envstr, tmpstr); i = 0; while (envstr[i] != PATHSEPCH && envstr[i] != 0 && envstr[i] != '.') { i++; } envstr[i] = '\0'; const char *envval = osd_getenv(&envstr[1]); if (envval != NULL) { j = strlen(envval) + strlen(tmpstr) + 1; osd_free(tmpstr); tmpstr = (char *) osd_malloc_array(j); // start with the value of $HOME strcpy(tmpstr, envval); // replace the null with a path separator again envstr[i] = PATHSEPCH; // append it strcat(tmpstr, &envstr[i]); } else fprintf(stderr, "Warning: osd_open environment variable %s not found.\n", envstr); osd_free(envstr); } #if defined(SDLMAME_WIN32) || defined(SDLMAME_OS2) access |= O_BINARY; #endif // attempt to open the file #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) || defined(SDLMAME_HAIKU) (*file)->handle = open(tmpstr, access, 0666); #else (*file)->handle = open64(tmpstr, access, 0666); #endif if ((*file)->handle == -1) { // create the path if necessary if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS)) { char *pathsep = strrchr(tmpstr, PATHSEPCH); if (pathsep != NULL) { int error; // create the path up to the file *pathsep = 0; error = create_path_recursive(tmpstr); *pathsep = PATHSEPCH; // attempt to reopen the file if (error == NO_ERROR) { #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) || defined(SDLMAME_HAIKU) (*file)->handle = open(tmpstr, access, 0666); #else (*file)->handle = open64(tmpstr, access, 0666); #endif } } } // if we still failed, clean up and osd_free if ((*file)->handle == -1) { osd_free(*file); *file = NULL; osd_free(tmpstr); return error_to_file_error(errno); } } // get the file size #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) || defined(SDLMAME_HAIKU) fstat((*file)->handle, &st); #else fstat64((*file)->handle, &st); #endif *filesize = (UINT64)st.st_size; error: // cleanup if (filerr != FILERR_NONE && *file != NULL) { osd_free(*file); *file = NULL; } if (tmpstr) osd_free(tmpstr); return filerr; }
osd_work_queue *osd_work_queue_alloc(int flags) { int threadnum; int numprocs = effective_num_processors(); osd_work_queue *queue; int osdthreadnum = 0; int allocthreadnum; char *osdworkqueuemaxthreads = osd_getenv(ENV_WORKQUEUEMAXTHREADS); // allocate a new queue queue = (osd_work_queue *)osd_malloc(sizeof(*queue)); if (queue == NULL) goto error; memset(queue, 0, sizeof(*queue)); // initialize basic queue members queue->tailptr = (osd_work_item **)&queue->list; queue->flags = flags; // allocate events for the queue queue->doneevent = osd_event_alloc(TRUE, TRUE); // manual reset, signalled if (queue->doneevent == NULL) goto error; // initialize the critical section queue->lock = osd_scalable_lock_alloc(); if (queue->lock == NULL) goto error; // determine how many threads to create... // on a single-CPU system, create 1 thread for I/O queues, and 0 threads for everything else if (numprocs == 1) threadnum = (flags & WORK_QUEUE_FLAG_IO) ? 1 : 0; // on an n-CPU system, create n-1 threads for multi queues, and 1 thread for everything else else threadnum = (flags & WORK_QUEUE_FLAG_MULTI) ? (numprocs - 1) : 1; if (osdworkqueuemaxthreads != NULL && sscanf(osdworkqueuemaxthreads, "%d", &osdthreadnum) == 1 && threadnum > osdthreadnum) threadnum = osdthreadnum; // clamp to the maximum queue->threads = MIN(threadnum, WORK_MAX_THREADS); // allocate memory for thread array (+1 to count the calling thread if WORK_QUEUE_FLAG_MULTI) if (flags & WORK_QUEUE_FLAG_MULTI) allocthreadnum = queue->threads + 1; else allocthreadnum = queue->threads; #if KEEP_STATISTICS printf("osdprocs: %d effecprocs: %d threads: %d allocthreads: %d osdthreads: %d maxthreads: %d queuethreads: %d\n", osd_num_processors, numprocs, threadnum, allocthreadnum, osdthreadnum, WORK_MAX_THREADS, queue->threads); #endif queue->thread = (work_thread_info *)osd_malloc_array(allocthreadnum * sizeof(queue->thread[0])); if (queue->thread == NULL) goto error; memset(queue->thread, 0, allocthreadnum * sizeof(queue->thread[0])); // iterate over threads for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = &queue->thread[threadnum]; // set a pointer back to the queue thread->queue = queue; // create the per-thread wake event thread->wakeevent = osd_event_alloc(FALSE, FALSE); // auto-reset, not signalled if (thread->wakeevent == NULL) goto error; // create the thread thread->handle = osd_thread_create(worker_thread_entry, thread); if (thread->handle == NULL) goto error; // set its priority: I/O threads get high priority because they are assumed to be // blocked most of the time; other threads just match the creator's priority if (flags & WORK_QUEUE_FLAG_IO) osd_thread_adjust_priority(thread->handle, 1); else osd_thread_adjust_priority(thread->handle, 0); } // start a timer going for "waittime" on the main thread if (flags & WORK_QUEUE_FLAG_MULTI) { begin_timing(queue->thread[queue->threads].waittime); } return queue; error: osd_work_queue_free(queue); return NULL; }
void sdlvideo_monitor_refresh(sdl_monitor_info *monitor) { #if (SDLMAME_SDL2) SDL_DisplayMode dmode; SDL_GetDesktopDisplayMode(monitor->handle, &dmode); monitor->monitor_width = dmode.w; monitor->monitor_height = dmode.h; monitor->center_width = dmode.w; monitor->center_height = dmode.h; #else #if defined(SDLMAME_WIN32) // Win32 version MONITORINFOEX info; info.cbSize = sizeof(info); GetMonitorInfo((HMONITOR)monitor->handle, (LPMONITORINFO)&info); monitor->center_width = monitor->monitor_width = info.rcMonitor.right - info.rcMonitor.left; monitor->center_height = monitor->monitor_height = info.rcMonitor.bottom - info.rcMonitor.top; char *temp = utf8_from_wstring(info.szDevice); strcpy(monitor->monitor_device, temp); osd_free(temp); #elif defined(SDLMAME_MACOSX) // Mac OS X Core Imaging version CGDirectDisplayID primary; CGRect dbounds; // get the main display primary = CGMainDisplayID(); dbounds = CGDisplayBounds(primary); monitor->center_width = monitor->monitor_width = dbounds.size.width - dbounds.origin.x; monitor->center_height = monitor->monitor_height = dbounds.size.height - dbounds.origin.y; strcpy(monitor->monitor_device, "Mac OS X display"); #elif defined(SDLMAME_X11) || defined(SDLMAME_NO_X11) // X11 version { #if defined(SDLMAME_X11) // X11 version int screen; SDL_SysWMinfo info; SDL_VERSION(&info.version); if ( SDL_GetWMInfo(&info) && (info.subsystem == SDL_SYSWM_X11) ) { screen = DefaultScreen(info.info.x11.display); SDL_VideoDriverName(monitor->monitor_device, sizeof(monitor->monitor_device)-1); monitor->monitor_width = DisplayWidth(info.info.x11.display, screen); monitor->monitor_height = DisplayHeight(info.info.x11.display, screen); if ((XineramaIsActive(info.info.x11.display)) && video_config.restrictonemonitor) { XineramaScreenInfo *xineinfo; int numscreens; xineinfo = XineramaQueryScreens(info.info.x11.display, &numscreens); monitor->center_width = xineinfo[0].width; monitor->center_height = xineinfo[0].height; XFree(xineinfo); } else { monitor->center_width = monitor->monitor_width; monitor->center_height = monitor->monitor_height; } } else #endif // defined(SDLMAME_X11) { static int first_call=0; static int cw = 0, ch = 0; SDL_VideoDriverName(monitor->monitor_device, sizeof(monitor->monitor_device)-1); if (first_call==0) { char *dimstr = osd_getenv(SDLENV_DESKTOPDIM); const SDL_VideoInfo *sdl_vi; sdl_vi = SDL_GetVideoInfo(); #if (SDL_VERSION_ATLEAST(1,2,10)) cw = sdl_vi->current_w; ch = sdl_vi->current_h; #endif first_call=1; if ((cw==0) || (ch==0)) { if (dimstr != NULL) { sscanf(dimstr, "%dx%d", &cw, &ch); } if ((cw==0) || (ch==0)) { mame_printf_warning("WARNING: SDL_GetVideoInfo() for driver <%s> is broken.\n", monitor->monitor_device); mame_printf_warning(" You should set SDLMAME_DESKTOPDIM to your desktop size.\n"); mame_printf_warning(" e.g. export SDLMAME_DESKTOPDIM=800x600\n"); mame_printf_warning(" Assuming 1024x768 now!\n"); cw=1024; ch=768; } } } monitor->monitor_width = cw; monitor->monitor_height = ch; monitor->center_width = cw; monitor->center_height = ch; } } #elif defined(SDLMAME_OS2) // OS2 version monitor->center_width = monitor->monitor_width = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ); monitor->center_height = monitor->monitor_height = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ); strcpy(monitor->monitor_device, "OS/2 display"); #else #error Unknown SDLMAME_xx OS type! #endif { static int info_shown=0; if (!info_shown) { mame_printf_verbose("SDL Device Driver : %s\n", monitor->monitor_device); mame_printf_verbose("SDL Monitor Dimensions: %d x %d\n", monitor->monitor_width, monitor->monitor_height); info_shown = 1; } } #endif // (SDLMAME_SDL2) }
osd_work_queue *osd_work_queue_alloc(int flags) { int threadnum; int numprocs = effective_num_processors(); osd_work_queue *queue; int osdthreadnum = 0; int allocthreadnum; const char *osdworkqueuemaxthreads = osd_getenv(ENV_WORKQUEUEMAXTHREADS); // allocate a new queue queue = new osd_work_queue(); // initialize basic queue members queue->tailptr = (osd_work_item **)&queue->list; queue->flags = flags; // determine how many threads to create... // on a single-CPU system, create 1 thread for I/O queues, and 0 threads for everything else if (numprocs == 1) threadnum = (flags & WORK_QUEUE_FLAG_IO) ? 1 : 0; // on an n-CPU system, create n-1 threads for multi queues, and 1 thread for everything else else threadnum = (flags & WORK_QUEUE_FLAG_MULTI) ? (numprocs - 1) : 1; if (osdworkqueuemaxthreads != nullptr && sscanf(osdworkqueuemaxthreads, "%d", &osdthreadnum) == 1 && threadnum > osdthreadnum) threadnum = osdthreadnum; // clamp to the maximum queue->threads = MIN(threadnum, WORK_MAX_THREADS); // allocate memory for thread array (+1 to count the calling thread if WORK_QUEUE_FLAG_MULTI) if (flags & WORK_QUEUE_FLAG_MULTI) allocthreadnum = queue->threads + 1; else allocthreadnum = queue->threads; #if KEEP_STATISTICS printf("osdprocs: %d effecprocs: %d threads: %d allocthreads: %d osdthreads: %d maxthreads: %d queuethreads: %d\n", osd_num_processors, numprocs, threadnum, allocthreadnum, osdthreadnum, WORK_MAX_THREADS, queue->threads); #endif for (threadnum = 0; threadnum < allocthreadnum; threadnum++) queue->thread.push_back(new work_thread_info(threadnum, *queue)); // iterate over threads for (threadnum = 0; threadnum < queue->threads; threadnum++) { work_thread_info *thread = queue->thread[threadnum]; // create the thread thread->handle = new std::thread(worker_thread_entry, thread); if (thread->handle == nullptr) goto error; // set its priority: I/O threads get high priority because they are assumed to be // blocked most of the time; other threads just match the creator's priority if (flags & WORK_QUEUE_FLAG_IO) thread_adjust_priority(thread->handle, 1); else thread_adjust_priority(thread->handle, 0); } // start a timer going for "waittime" on the main thread if (flags & WORK_QUEUE_FLAG_MULTI) { begin_timing(queue->thread[queue->threads]->waittime); } return queue; error: osd_work_queue_free(queue); return nullptr; }
void sdl_monitor_info::refresh() { #if (SDLMAME_SDL2) SDL_DisplayMode dmode; #if defined(SDLMAME_WIN32) SDL_GetDesktopDisplayMode(m_handle, &dmode); #else SDL_GetCurrentDisplayMode(m_handle, &dmode); #endif SDL_Rect dimensions; SDL_GetDisplayBounds(m_handle, &dimensions); m_pos_size = SDL_Rect_to_osd_rect(dimensions); m_usuable_pos_size = SDL_Rect_to_osd_rect(dimensions); m_is_primary = (m_handle == 0); #else #if defined(SDLMAME_WIN32) // Win32 version MONITORINFOEX info; info.cbSize = sizeof(info); GetMonitorInfo((HMONITOR)m_handle, (LPMONITORINFO)&info); m_pos_size = RECT_to_osd_rect(info.rcMonitor); m_usuable_pos_size = RECT_to_osd_rect(info.rcWork); m_is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) != 0); char *temp = utf8_from_wstring(info.szDevice); strncpy(m_name, temp, ARRAY_LENGTH(m_name) - 1); osd_free(temp); #elif defined(SDLMAME_MACOSX) // Mac OS X Core Imaging version CGDirectDisplayID primary; CGRect dbounds; // get the main display primary = CGMainDisplayID(); dbounds = CGDisplayBounds(primary); m_is_primary = (m_handle == 0); m_pos_size = osd_rect(0, 0, dbounds.size.width - dbounds.origin.x, dbounds.size.height - dbounds.origin.y); m_usuable_pos_size = m_pos_size; strncpy(m_name, "Mac OS X display", ARRAY_LENGTH(m_name) - 1); #elif defined(SDLMAME_X11) || defined(SDLMAME_NO_X11) // X11 version { #if defined(SDLMAME_X11) // X11 version int screen; SDL_SysWMinfo info; SDL_VERSION(&info.version); if ( SDL_GetWMInfo(&info) && (info.subsystem == SDL_SYSWM_X11) ) { screen = DefaultScreen(info.info.x11.display); SDL_VideoDriverName(m_name, ARRAY_LENGTH(m_name) - 1); m_pos_size = osd_rect(0, 0, DisplayWidth(info.info.x11.display, screen), DisplayHeight(info.info.x11.display, screen)); /* FIXME: If Xinerame is used we should compile a list of monitors * like we do for other targets and ignore SDL. */ if ((XineramaIsActive(info.info.x11.display)) && video_config.restrictonemonitor) { XineramaScreenInfo *xineinfo; int numscreens; xineinfo = XineramaQueryScreens(info.info.x11.display, &numscreens); m_pos_size = osd_rect(0, 0, xineinfo[0].width, xineinfo[0].height); XFree(xineinfo); } m_usuable_pos_size = m_pos_size; m_is_primary = (m_handle == 0); } else #endif // defined(SDLMAME_X11) { static int first_call=0; static int cw = 0, ch = 0; SDL_VideoDriverName(m_name, ARRAY_LENGTH(m_name) - 1); if (first_call==0) { const char *dimstr = osd_getenv(SDLENV_DESKTOPDIM); const SDL_VideoInfo *sdl_vi; sdl_vi = SDL_GetVideoInfo(); #if (SDL_VERSION_ATLEAST(1,2,10)) cw = sdl_vi->current_w; ch = sdl_vi->current_h; #endif first_call=1; if ((cw==0) || (ch==0)) { if (dimstr != NULL) { sscanf(dimstr, "%dx%d", &cw, &ch); } if ((cw==0) || (ch==0)) { osd_printf_warning("WARNING: SDL_GetVideoInfo() for driver <%s> is broken.\n", m_name); osd_printf_warning(" You should set SDLMAME_DESKTOPDIM to your desktop size.\n"); osd_printf_warning(" e.g. export SDLMAME_DESKTOPDIM=800x600\n"); osd_printf_warning(" Assuming 1024x768 now!\n"); cw=1024; ch=768; } } } m_pos_size = osd_rect(0, 0, cw, ch); m_usuable_pos_size = m_pos_size; m_is_primary = (m_handle == 0); } } #elif defined(SDLMAME_OS2) // OS2 version m_pos_size = osd_rect(0, 0, WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN ), WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) ); m_usuable_pos_size = m_pos_size; m_is_primary = (m_handle == 0); strncpy(m_name, "OS/2 display", ARRAY_LENGTH(m_name) - 1); #else #error Unknown SDLMAME_xx OS type! #endif { static int info_shown=0; if (!info_shown) { osd_printf_verbose("SDL Device Driver : %s\n", m_name); osd_printf_verbose("SDL Monitor Dimensions: %d x %d\n", m_pos_size.width(), m_pos_size.height()); info_shown = 1; } } #endif // (SDLMAME_SDL2) }
osd_directory *osd_opendir(const char *dirname) { osd_directory *dir = NULL; char *tmpstr, *envstr; int i, j; dir = (osd_directory *) osd_malloc(sizeof(osd_directory)); if (dir) { memset(dir, 0, sizeof(osd_directory)); dir->fd = NULL; } tmpstr = (char *) osd_malloc_array(strlen(dirname)+1); strcpy(tmpstr, dirname); if (tmpstr[0] == '$') { envstr = (char *) osd_malloc_array(strlen(tmpstr)+1); strcpy(envstr, tmpstr); i = 0; while (envstr[i] != PATHSEPCH && envstr[i] != INVPATHSEPCH && envstr[i] != 0 && envstr[i] != '.') { i++; } envstr[i] = '\0'; const char *envval = osd_getenv(&envstr[1]); if (envval != NULL) { j = strlen(envval) + strlen(tmpstr) + 1; osd_free(tmpstr); tmpstr = (char *) osd_malloc_array(j); // start with the value of $HOME strcpy(tmpstr, envval); // replace the null with a path separator again envstr[i] = PATHSEPCH; // append it strcat(tmpstr, &envstr[i]); } else fprintf(stderr, "Warning: osd_opendir environment variable %s not found.\n", envstr); osd_free(envstr); } dir->fd = opendir(tmpstr); dir->path = tmpstr; if (dir && (dir->fd == NULL)) { osd_free(dir->path); osd_free(dir); dir = NULL; } return dir; }