Esempio n. 1
0
int32
runtime·semasleep(int64 ns)
{
	Timespec ts;

	// spin-mutex lock
	while(runtime·xchg(&m->waitsemalock, 1))
		runtime·osyield();

	for(;;) {
		// lock held
		if(m->waitsemacount == 0) {
			// sleep until semaphore != 0 or timeout.
			// thrsleep unlocks m->waitsemalock.
			if(ns < 0)
				runtime·thrsleep(&m->waitsemacount, 0, nil, &m->waitsemalock, nil);
			else {
				ns += runtime·nanotime();
				// NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
				ts.tv_nsec = 0;
				ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
				runtime·thrsleep(&m->waitsemacount, CLOCK_MONOTONIC, &ts, &m->waitsemalock, nil);
			}
			// reacquire lock
			while(runtime·xchg(&m->waitsemalock, 1))
				runtime·osyield();
		}

		// lock held (again)
		if(m->waitsemacount != 0) {
			// semaphore is available.
			m->waitsemacount--;
			// spin-mutex unlock
			runtime·atomicstore(&m->waitsemalock, 0);
			return 0;  // semaphore acquired
		}

		// semaphore not available.
		// if there is a timeout, stop now.
		// otherwise keep trying.
		if(ns >= 0)
			break;
	}

	// lock held but giving up
	// spin-mutex unlock
	runtime·atomicstore(&m->waitsemalock, 0);
	return -1;
}
Esempio n. 2
0
int32
runtime·semasleep(int64 ns)
{
	// store ms in ns to save stack space
	if(ns < 0)
		ns = INFINITE;
	else {
		ns = runtime·timediv(ns, 1000000, nil);
		if(ns == 0)
			ns = 1;
	}
	if(runtime·stdcall(runtime·WaitForSingleObject, 2, m->waitsema, (uintptr)ns) != 0)
		return -1;  // timeout
	return 0;
}
Esempio n. 3
0
int32
runtime·semasleep(int64 ns)
{
	int32 ret;
	
	ret = runtime·nacl_mutex_lock(m->waitsemalock);
	if(ret < 0) {
		//runtime·printf("nacl_mutex_lock: error %d\n", -ret);
		runtime·throw("semasleep");
	}
	if(m->waitsemacount > 0) {
		m->waitsemacount = 0;
		runtime·nacl_mutex_unlock(m->waitsemalock);
		return 0;
	}

	while(m->waitsemacount == 0) {
		if(ns < 0) {
			ret = runtime·nacl_cond_wait(m->waitsema, m->waitsemalock);
			if(ret < 0) {
				//runtime·printf("nacl_cond_wait: error %d\n", -ret);
				runtime·throw("semasleep");
			}
		} else {
			Timespec ts;
			
			ns += runtime·nanotime();
			ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
			ret = runtime·nacl_cond_timed_wait_abs(m->waitsema, m->waitsemalock, &ts);
			if(ret == -ETIMEDOUT) {
				runtime·nacl_mutex_unlock(m->waitsemalock);
				return -1;
			}
			if(ret < 0) {
				//runtime·printf("nacl_cond_timed_wait_abs: error %d\n", -ret);
				runtime·throw("semasleep");
			}
		}
	}
			
	m->waitsemacount = 0;
	runtime·nacl_mutex_unlock(m->waitsemalock);
	return 0;
}
Esempio n. 4
0
int32
runtime·semasleep(int64 ns)
{
	Timespec ts;

	// spin-mutex lock
	while(runtime·xchg(&m->waitsemalock, 1))
		runtime·osyield();

	for(;;) {
		// lock held
		if(m->waitsemacount == 0) {
			// sleep until semaphore != 0 or timeout.
			// thrsleep unlocks m->waitsemalock.
			if(ns < 0) {
				// TODO(jsing) - potential deadlock!
				//
				// There is a potential deadlock here since we
				// have to release the waitsemalock mutex
				// before we call lwp_park() to suspend the
				// thread. This allows another thread to
				// release the lock and call lwp_unpark()
				// before the thread is actually suspended.
				// If this occurs the current thread will end
				// up sleeping indefinitely. Unfortunately
				// the NetBSD kernel does not appear to provide
				// a mechanism for unlocking the userspace
				// mutex once the thread is actually parked.
				runtime·atomicstore(&m->waitsemalock, 0);
				runtime·lwp_park(nil, 0, &m->waitsemacount, nil);
			} else {
				ns = ns + runtime·nanotime();
				// NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
				ts.tv_nsec = 0;
				ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
				// TODO(jsing) - potential deadlock!
				// See above for details.
				runtime·atomicstore(&m->waitsemalock, 0);
				runtime·lwp_park(&ts, 0, &m->waitsemacount, nil);
			}
			// reacquire lock
			while(runtime·xchg(&m->waitsemalock, 1))
				runtime·osyield();
		}

		// lock held (again)
		if(m->waitsemacount != 0) {
			// semaphore is available.
			m->waitsemacount--;
			// spin-mutex unlock
			runtime·atomicstore(&m->waitsemalock, 0);
			return 0;  // semaphore acquired
		}

		// semaphore not available.
		// if there is a timeout, stop now.
		// otherwise keep trying.
		if(ns >= 0)
			break;
	}

	// lock held but giving up
	// spin-mutex unlock
	runtime·atomicstore(&m->waitsemalock, 0);
	return -1;
}