static bool _releasemutex( uintptr_t hndl ) { int rc; pthread_mutex_t* pm; pm = *(pthread_mutex_t**)hndl; rc = pthread_mutex_unlock (pm); if ( rc != 0 ) { _setlasterror( get_win_error (rc) ); return false; } return true; }
static unsigned _waitforsinglemutexobject( uintptr_t hndl, unsigned milliseconds ) { int rc; pthread_mutex_t *pm; pm = *(pthread_mutex_t**)hndl; if ( milliseconds != INFINITE ) { struct timespec abstime; #ifdef __MACH__ clock_serv_t cclock; mach_timespec_t mts; host_get_clock_service (mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time (cclock, &mts); mach_port_deallocate (mach_task_self(), cclock); abstime.tv_sec = mts.tv_sec; abstime.tv_nsec = mts.tv_nsec; #else clock_gettime (CLOCK_REALTIME, &abstime); #endif abstime.tv_sec += (milliseconds / 1000); abstime.tv_nsec += (milliseconds % 1000) * 1000000; rc = pthread_mutex_timedlock (pm, &abstime); } else rc = pthread_mutex_lock (pm); if ( rc != 0 ) { _setlasterror( get_win_error (rc) ); return (rc == ETIMEDOUT ? WAIT_TIMEOUT : WAIT_FAILED); } return WAIT_OBJECT_0; }
uintptr_t _createmutexex( SECURITY_ATTRIBUTES *sa, const char *name, unsigned flags, unsigned access ) { //NOTE: Windows critical sections are recursive //NOTE: posix recursive mutexes don't return error code int rc; pthread_mutex_t *pm; pthread_mutexattr_t mattr; int fd_mutex = -1; char shmname[MAX_PATH+1]; size_t namelen = 0; bool opened = false; uintptr_t hndl; if ( name && *name ) { namelen = strlen (name); if ( 1+namelen > NAME_MAX ) { _setlasterror( ERROR_BAD_ARGUMENTS ); return (uintptr_t)NULL; } shmname[0] = '/'; strcpy (shmname+1, name); //try to open mutex first fd_mutex = shm_open (shmname, O_RDWR, S_IRUSR|S_IWUSR); if ( fd_mutex != -1 ) { struct flock fl; fl.l_type = F_WRLCK; //note: check only fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = getpid (); rc = fcntl (fd_mutex, F_GETLK, &fl); if (!(rc == 0 && fl.l_type == F_RDLCK)) { //semaphore is unused or other error ftruncate (fd_mutex, sizeof(pthread_mutex_t)); } else { _setlasterror( ERROR_ALREADY_EXISTS ); opened = true; } } else { //create new semaphore fd_mutex = shm_open (shmname, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); if ( fd_mutex == -1 ) { _setlasterror( get_win_error (errno) ); return (uintptr_t)NULL; } ftruncate (fd_mutex, sizeof(pthread_mutex_t)); } void *addr_mutex = mmap (0, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd_mutex, 0); if (addr_mutex == MAP_FAILED) { _setlasterror( get_win_error (errno) ); close (fd_mutex); if (!opened) shm_unlink (shmname); return (uintptr_t)NULL; } //add file open check struct flock fl; fl.l_type = F_RDLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = getpid (); fcntl (fd_mutex, F_SETLK, &fl); pm = (pthread_mutex_t *)addr_mutex; } else { pm = (pthread_mutex_t *) malloc (sizeof(pthread_mutex_t)); if ( !pm ) { _setlasterror( get_win_error (errno) ); //ERROR_NOT_ENOUGH_MEMORY return (uintptr_t)NULL; } } if (!opened) { //initialize mutex pthread_mutexattr_init (&mattr); if ( name && *name ) pthread_mutexattr_setpshared (&mattr, PTHREAD_PROCESS_SHARED); else pthread_mutexattr_setpshared (&mattr, PTHREAD_PROCESS_PRIVATE); #if defined (__linux__) || defined (__bsd__) pthread_mutexattr_setkind_np (&mattr, PTHREAD_MUTEX_RECURSIVE_NP); #else pthread_mutexattr_settype (&mattr, PTHREAD_MUTEX_RECURSIVE); #endif rc = pthread_mutex_init (pm, &mattr); pthread_mutexattr_destroy (&mattr); if ( rc != 0 ) { _setlasterror( get_win_error (rc) ); if ( name && *name ) { munmap ((void*)pm, sizeof(pthread_mutex_t)); shm_unlink (shmname); close (fd_mutex); } else free (pm); return (uintptr_t)NULL; } } size_t datalen = sizeof(MUTEXOBJDATA) + (name ? namelen+2 : 0); MUTEXOBJDATA* data; data = (MUTEXOBJDATA*)malloc (datalen); if (!data) { _setlasterror( get_win_error (rc) ); if ( name && *name ) { munmap ((void*)pm, sizeof(pthread_mutex_t)); if (!opened) shm_unlink (shmname); close (fd_mutex); } else free (pm); return (uintptr_t)NULL; } data->fdmutex = fd_mutex; strcpy (data->name, (name && *name ? shmname : "")); //(flags && CREATE_MUTEX_INITIAL_OWNER) hndl = _createhandle (-1, 0, &mutexkrnlobj, &pm, sizeof(void*), data, datalen); if ( !hndl ) { _setlasterror( get_win_error (errno) ); pthread_mutex_destroy (pm); //destroy created mutex if ( name && *name ) { munmap ((void*)pm, sizeof(pthread_mutex_t)); if (!opened) shm_unlink (shmname); close (fd_mutex); } else free (pm); free (data); return (uintptr_t)NULL; } free (data); return hndl; }
uintptr_t _openmutex( unsigned access, bool inherit, const char *name ) { int rc; pthread_mutex_t *pm; char shmname[MAX_PATH+1]; size_t namelen = 0; uintptr_t hndl; if (name) namelen = strlen (name); if ( !(name && *name) || 1+namelen > MAX_PATH ) { _setlasterror( ERROR_BAD_ARGUMENTS ); return (uintptr_t)NULL; } shmname[0] = '/'; strcpy (shmname+1, name); //first try to find existing mutex int fd_mutex = shm_open (shmname, O_RDWR, S_IRUSR|S_IWUSR); if ( fd_mutex == -1 ) { _setlasterror( get_win_error (errno) ); return (uintptr_t)NULL; } struct flock fl; fl.l_type = F_WRLCK; //note: check only fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; fl.l_pid = getpid (); rc = fcntl (fd_mutex, F_GETLK, &fl); if (!(rc == 0 && fl.l_type == F_RDLCK)) { //mutex is unused or other error close (fd_mutex); return (uintptr_t)NULL; } //semaphore exists, try to set read lock fl.l_type = F_RDLCK; rc = fcntl (fd_mutex, F_SETLK, &fl); if (rc != 0) { close (fd_mutex); return (uintptr_t)NULL; } void *addr_mutex = mmap (0, sizeof(pthread_mutex_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd_mutex, 0); if (addr_mutex == MAP_FAILED) { _setlasterror( get_win_error (errno) ); close (fd_mutex); return (uintptr_t)NULL; } pm = (pthread_mutex_t *)addr_mutex; size_t datalen = sizeof(MUTEXOBJDATA) + (name ? namelen+2 : 0); MUTEXOBJDATA *data; data = (MUTEXOBJDATA*)malloc (datalen); if (!data) { _setlasterror( get_win_error (errno) ); munmap ((void*)pm, sizeof(pthread_mutex_t)); close (fd_mutex); return (uintptr_t)NULL; } data->fdmutex = fd_mutex; strcpy (data->name, (name ? name : "")); hndl = _createhandle (-1, 0, &mutexkrnlobj, &pm, sizeof(void*), data, datalen); if ( !hndl ) { _setlasterror( get_win_error (errno) ); munmap ((void*)pm, sizeof(pthread_mutex_t)); close (fd_mutex); return (uintptr_t)NULL; } return hndl; }
char *discover_system_java_home(void) { #ifdef WIN32 HKEY key; HRESULT result; const char *key_root = "SOFTWARE\\JavaSoft\\Java Development Kit"; struct string *string; char buffer[PATH_MAX]; DWORD valuelen = sizeof(buffer); result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key_root, 0, KEY_READ, &key); if (ERROR_SUCCESS != result) return NULL; result = RegQueryValueEx(key, "CurrentVersion", NULL, NULL, (LPBYTE)buffer, &valuelen); RegCloseKey(key); if (ERROR_SUCCESS != result) { error(get_win_error()); return NULL; } string = string_initf("%s\\%s", key_root, buffer); result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, string->buffer, 0, KEY_READ, &key); if (ERROR_SUCCESS != result) return NULL; valuelen = sizeof(buffer); result = RegQueryValueEx(key, "JavaHome", NULL, NULL, (LPBYTE)buffer, &valuelen); RegCloseKey(key); if (ERROR_SUCCESS != result) return NULL; return strdup(buffer); #else const char *java_executable = find_in_path(get_java_command(), 0); #ifdef __APPLE__ int len = strlen(java_executable); if (len > 14 && !suffixcmp(java_executable, len, "/Commands/java")) { /* * Containing folder is not a JRE or JDK, it's an Apple Framework. Bah! * For example, the path: * * /System/Library/Frameworks/JavaVM.framework/Versions/A/Commands * * does not actually contain a proper JRE. It is merely a Framework * for the current version of Apple Java on the system. * * Unfortunately, on OS X, /usr/bin/java is typically symlinked to * /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java, * with Current symlinked to A, resulting in a failure of this PATH-based * strategy to find the actual JRE. So we simply give up in that case. */ if (debug) error("Ignoring Apple Framework java executable: '%s'", java_executable); return NULL; } #endif if (java_executable) { char *path = strdup(java_executable); const char *suffixes[] = { "java", "\\", "/", "bin", "\\", "/", NULL }; int len = strlen(path), i; for (i = 0; suffixes[i]; i++) if (!suffixcmp(path, len, suffixes[i])) { len -= strlen(suffixes[i]); path[len] = '\0'; } return path; } return NULL; #endif }