Exemple #1
0
static gboolean mutex_is_owned (gpointer handle)
{
	struct _WapiHandle_mutex *mutex_handle;
	gboolean ok;
	
	ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
				(gpointer *)&mutex_handle);
	if(ok==FALSE) {
		g_warning ("%s: error looking up mutex handle %p", __func__,
			   handle);
		return(FALSE);
	}
	
#ifdef DEBUG
	g_message("%s: testing ownership mutex handle %p", __func__, handle);
#endif

	if (mutex_handle->recursion > 0 &&
	    mutex_handle->pid == _wapi_getpid () &&
	    pthread_equal (mutex_handle->tid, pthread_self ())) {
#ifdef DEBUG
		g_message ("%s: mutex handle %p owned by %d:%ld", __func__,
			   handle, _wapi_getpid (), pthread_self ());
#endif

		return(TRUE);
	} else {
#ifdef DEBUG
		g_message ("%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, _wapi_getpid (), pthread_self (), mutex_handle->recursion, mutex_handle->pid, mutex_handle->tid);
#endif

		return(FALSE);
	}
}
Exemple #2
0
static gboolean namedmutex_is_owned (gpointer handle)
{
	struct _WapiHandle_namedmutex *namedmutex_handle;
	gboolean ok;
	
	ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
				  (gpointer *)&namedmutex_handle);
	if (ok == FALSE) {
		g_warning ("%s: error looking up mutex handle %p", __func__,
			   handle);
		return(FALSE);
	}
	
	DEBUG ("%s: testing ownership mutex handle %p", __func__, handle);

	if (namedmutex_handle->recursion > 0 &&
	    namedmutex_handle->pid == _wapi_getpid () &&
	    pthread_equal (namedmutex_handle->tid, pthread_self ())) {
		DEBUG ("%s: mutex handle %p owned by %d:%ld", __func__,
			   handle, _wapi_getpid (), pthread_self ());

		return(TRUE);
	} else {
		DEBUG ("%s: mutex handle %p not owned by %d:%ld, but locked %d times by %d:%ld", __func__, handle, _wapi_getpid (), pthread_self (), namedmutex_handle->recursion, namedmutex_handle->pid, namedmutex_handle->tid);

		return(FALSE);
	}
}
Exemple #3
0
/* NB, always called with the shared handle lock held */
static gboolean namedmutex_own (gpointer handle)
{
	struct _WapiHandle_namedmutex *namedmutex_handle;
	gboolean ok;
	
	DEBUG ("%s: owning named mutex handle %p", __func__, handle);
	
	ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
				  (gpointer *)&namedmutex_handle);
	if (ok == FALSE) {
		g_warning ("%s: error looking up named mutex handle %p",
			   __func__, handle);
		return(FALSE);
	}

	_wapi_thread_own_mutex (handle);

	namedmutex_handle->pid = _wapi_getpid ();
	namedmutex_handle->tid = pthread_self ();
	namedmutex_handle->recursion++;

	_wapi_shared_handle_set_signal_state (handle, FALSE);

	DEBUG ("%s: mutex handle %p locked %d times by %d:%ld", __func__,
		   handle, namedmutex_handle->recursion,
		   namedmutex_handle->pid, namedmutex_handle->tid);
	
	return(TRUE);
}
Exemple #4
0
static gboolean mutex_own (gpointer handle)
{
	struct _WapiHandle_mutex *mutex_handle;
	gboolean ok;
	
	ok = _wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
				  (gpointer *)&mutex_handle);
	if (ok == FALSE) {
		g_warning ("%s: error looking up mutex handle %p", __func__,
			   handle);
		return(FALSE);
	}

	_wapi_thread_own_mutex (handle);
	
#ifdef DEBUG
	g_message("%s: owning mutex handle %p", __func__, handle);
#endif

	_wapi_handle_set_signal_state (handle, FALSE, FALSE);
	
	mutex_handle->pid = _wapi_getpid ();
	mutex_handle->tid = pthread_self ();
	mutex_handle->recursion++;

#ifdef DEBUG
	g_message ("%s: mutex handle %p locked %d times by %d:%ld", __func__,
		   handle, mutex_handle->recursion, mutex_handle->pid,
		   mutex_handle->tid);
#endif

	return(TRUE);
}
Exemple #5
0
static void
shm_semaphores_remove (void)
{
	int thr_ret;
	int proc_count;
	gchar *shm_name;
	
	DEBUGLOG ("%s: Checking process count (%d)", __func__, _wapi_getpid ());
	
	thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);
	g_assert (thr_ret == 0);
	
	proc_count = semctl (_wapi_sem_id, _WAPI_SHARED_SEM_PROCESS_COUNT,
			     GETVAL);

	g_assert (proc_count > 0);
	if (proc_count == 1) {
		/*
		 * Just us, so blow away the semaphores and the shared
		 * files
		 */
		DEBUGLOG ("%s: Removing semaphores! (%d)", __func__, _wapi_getpid ());

		semctl (_wapi_sem_id, 0, IPC_RMID);
#ifdef USE_SHM
		shm_name = _wapi_shm_shm_name (WAPI_SHM_DATA);
		shm_unlink (shm_name);
		g_free (shm_name);

		shm_name = _wapi_shm_shm_name (WAPI_SHM_FILESHARE);
		shm_unlink (shm_name);
		g_free (shm_name);
#endif
		unlink (_wapi_shm_file (WAPI_SHM_DATA));
		unlink (_wapi_shm_file (WAPI_SHM_FILESHARE));
	} else {
		/*
		 * "else" clause, because there's no point unlocking
		 * the semaphore if we've just blown it away...
		 */
		_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);
	}
}
Exemple #6
0
/* The shared state is not locked when prewait methods are called */
static void namedmutex_prewait (gpointer handle)
{
	/* If the mutex is not currently owned, do nothing and let the
	 * usual wait carry on.  If it is owned, check that the owner
	 * is still alive; if it isn't we override the previous owner
	 * and assume that process exited abnormally and failed to
	 * clean up.
	 */
	struct _WapiHandle_namedmutex *namedmutex_handle;
	gboolean ok;
	
	ok = _wapi_lookup_handle (handle, WAPI_HANDLE_NAMEDMUTEX,
				  (gpointer *)&namedmutex_handle);
	if (ok == FALSE) {
		g_warning ("%s: error looking up named mutex handle %p",
			   __func__, handle);
		return;
	}
	
	DEBUG ("%s: Checking ownership of named mutex handle %p", __func__,
		   handle);

	if (namedmutex_handle->recursion == 0) {
		DEBUG ("%s: Named mutex handle %p not owned", __func__,
			   handle);
	} else if (namedmutex_handle->pid == _wapi_getpid ()) {
		DEBUG ("%s: Named mutex handle %p owned by this process",
			   __func__, handle);
	} else {
		int thr_ret;
		gpointer proc_handle;
		
		DEBUG ("%s: Named mutex handle %p owned by another process", __func__, handle);
		proc_handle = OpenProcess (0, 0, namedmutex_handle->pid);
		if (proc_handle == NULL) {
			/* Didn't find the process that this handle
			 * was owned by, overriding it
			 */
			DEBUG ("%s: overriding old owner of named mutex handle %p", __func__, handle);
			thr_ret = _wapi_handle_lock_shared_handles ();
			g_assert (thr_ret == 0);

			namedmutex_handle->pid = 0;
			namedmutex_handle->tid = 0;
			namedmutex_handle->recursion = 0;

			_wapi_shared_handle_set_signal_state (handle, TRUE);
			_wapi_handle_unlock_shared_handles ();
		} else {
			DEBUG ("%s: Found active pid %d for named mutex handle %p", __func__, namedmutex_handle->pid, handle);
		}
		if (proc_handle != NULL)
			CloseProcess (proc_handle);
	}
}
Exemple #7
0
/* Called by thread_exit(), but maybe indirectly by
 * mono_thread_manage() via mono_thread_signal_self() too
 */
static void _wapi_thread_abandon_mutexes (gpointer handle)
{
	struct _WapiHandle_thread *thread_handle;
	gboolean ok;
	int i;
	pid_t pid = _wapi_getpid ();
	pthread_t tid = pthread_self ();
	
#ifdef DEBUG
	g_message ("%s: Thread %p abandoning held mutexes", __func__, handle);
#endif

	if (handle == NULL) {
		handle = _wapi_thread_handle_from_id (pthread_self ());
		if (handle == NULL) {
			/* Something gone badly wrong... */
			return;
		}
	}
	
	ok = _wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
				  (gpointer *)&thread_handle);
	if (ok == FALSE) {
		g_warning ("%s: error looking up thread handle %p", __func__,
			   handle);
		return;
	}
	
	if (!pthread_equal (thread_handle->id, tid)) {
		return;
	}
	
	for (i = 0; i < thread_handle->owned_mutexes->len; i++) {
		gpointer mutex = g_ptr_array_index (thread_handle->owned_mutexes, i);
		
		_wapi_mutex_abandon (mutex, pid, tid);
		_wapi_thread_disown_mutex (mutex);
	}
}
Exemple #8
0
static void
shm_semaphores_init (void)
{
	key_t key;
	key_t oldkey;
	int thr_ret;
	struct _WapiHandleSharedLayout *tmp_shared;
	gchar *ftmp;
	gchar *filename;
	
	/*
	 * Yet more barmy API - this union is a well-defined parameter
	 * in a syscall, yet I still have to define it here as it
	 * doesn't appear in a header
	 */
	union semun {
		int val;
		struct semid_ds *buf;
		ushort *array;
	} defs;
	ushort def_vals[_WAPI_SHARED_SEM_COUNT];
	int i;
	int retries = 0;
	
	for (i = 0; i < _WAPI_SHARED_SEM_COUNT; i++) {
		def_vals[i] = 1;
	}

	/*
	 * Process count must start at '0' - the 1 for all the others
	 * sets the semaphore to "unlocked"
	 */
	def_vals[_WAPI_SHARED_SEM_PROCESS_COUNT] = 0;
	
	defs.array = def_vals;
	
	/*
	 *Temporarily attach the shared data so we can read the
	 * semaphore key.  We release this mapping and attach again
	 * after getting the semaphores to avoid a race condition
	 * where a terminating process can delete the shared files
	 * between a new process attaching the file and getting access
	 * to the semaphores (which increments the process count,
	 * preventing destruction of the shared data...)
	 */
	tmp_shared = _wapi_shm_attach (WAPI_SHM_DATA);
	g_assert (tmp_shared != NULL);
	
#ifdef USE_SHM
	ftmp=_wapi_shm_shm_name (WAPI_SHM_DATA);
	filename = g_build_filename ("/dev/shm", ftmp, NULL);
	g_assert (filename!=NULL);
	key = ftok (filename, 'M');
	g_free (ftmp);
	g_free (filename);
#else
	key = ftok ( _wapi_shm_file (WAPI_SHM_DATA), 'M');
#endif

again:
	retries++;
	oldkey = tmp_shared->sem_key;

	if (oldkey == 0) {
		DEBUGLOG ("%s: Creating with new key (0x%x)", __func__, key);

		/*
		 * The while loop attempts to make some sense of the
		 * bonkers 'think of a random number' method of
		 * picking a key without collision with other
		 * applications
		 */
		while ((_wapi_sem_id = semget (key, _WAPI_SHARED_SEM_COUNT,
					       IPC_CREAT | IPC_EXCL | 0600)) == -1) {
			if (errno == ENOMEM) {
				g_error ("%s: semget error: %s", __func__,
					    g_strerror (errno));
			} else if (errno == ENOSPC) {
				g_error ("%s: semget error: %s.  Try deleting some semaphores with ipcs and ipcrm\nor increase the maximum number of semaphore in the system.", __func__, g_strerror (errno));
			} else if (errno != EEXIST) {
				if (retries > 3)
					g_warning ("%s: semget error: %s key 0x%x - trying again", __func__,
							g_strerror (errno), key);
			}
			
			key++;
			DEBUGLOG ("%s: Got (%s), trying with new key (0x%x)", __func__, g_strerror (errno), key);
		}
		/*
		 * Got a semaphore array, so initialise it and install
		 * the key into the shared memory
		 */
		
		if (semctl (_wapi_sem_id, 0, SETALL, defs) == -1) {
			if (retries > 3)
				g_warning ("%s: semctl init error: %s - trying again", __func__, g_strerror (errno));

			/*
			 * Something went horribly wrong, so try
			 * getting a new set from scratch
			 */
			semctl (_wapi_sem_id, 0, IPC_RMID);
			goto again;
		}

		if (InterlockedCompareExchange (&tmp_shared->sem_key,
						key, 0) != 0) {
			/*
			 * Someone else created one and installed the
			 * key while we were working, so delete the
			 * array we created and fall through to the
			 * 'key already known' case.
			 */
			semctl (_wapi_sem_id, 0, IPC_RMID);
			oldkey = tmp_shared->sem_key;
		} else {
			/*
			 * We've installed this semaphore set's key into
			 * the shared memory
			 */
			goto done;
		}
	}
	
	DEBUGLOG ("%s: Trying with old key 0x%x", __func__, oldkey);

	_wapi_sem_id = semget (oldkey, _WAPI_SHARED_SEM_COUNT, 0600);
	if (_wapi_sem_id == -1) {
		if (retries > 3)
			g_warning ("%s: semget error opening old key 0x%x (%s) - trying again",
					__func__, oldkey,g_strerror (errno));

		/*
		 * Someone must have deleted the semaphore set, so
		 * blow away the bad key and try again
		 */
		InterlockedCompareExchange (&tmp_shared->sem_key, 0, oldkey);
		
		goto again;
	}

  done:
	/* Increment the usage count of this semaphore set */
	thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);
	g_assert (thr_ret == 0);
	
	DEBUGLOG ("%s: Incrementing the process count (%d)", __func__, _wapi_getpid ());

	/*
	 * We only ever _unlock_ this semaphore, letting the kernel
	 * restore (ie decrement) this unlock when this process exits.
	 * We lock another semaphore around it so we can serialise
	 * access when we're testing the value of this semaphore when
	 * we exit cleanly, so we can delete the whole semaphore set.
	 */
	_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_PROCESS_COUNT);

	DEBUGLOG ("%s: Process count is now %d (%d)", __func__, semctl (_wapi_sem_id, _WAPI_SHARED_SEM_PROCESS_COUNT, GETVAL), _wapi_getpid ());
	
	_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_PROCESS_COUNT_LOCK);

	if (_wapi_shm_disabled)
		g_free (tmp_shared);
	else
		munmap (tmp_shared, sizeof(struct _WapiHandleSharedLayout));
}