// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "runtime.h"
#include "defs.h"
#include "os.h"

int8 *goos = "nacl";

// Thread-safe allocation of a mutex.
// (The name sema is left over from the Darwin implementation.
// Native Client implements semaphores too, but it is just a shim
// over the host implementation, which on some hosts imposes a very
// low limit on how many semaphores can be created.)
//
// Psema points at a mutex descriptor.
// It starts out zero, meaning no mutex.
// Fill it in, being careful of others calling initsema
// simultaneously.
static void
initsema(uint32 *psema)
{
	uint32 sema;

	if(*psema != 0)	// already have one
		return;

	sema = mutex_create();
	if((int32)sema < 0) {
		printf("mutex_create failed\n");
		breakpoint();
	}
	// mutex_create returns a file descriptor;
	// shift it up and add the 1 bit so that can
	// distinguish unintialized from fd 0.
	sema = (sema<<1) | 1;
	if(!cas(psema, 0, sema)){
		// Someone else filled it in.  Use theirs.
		close(sema);
		return;
	}
}

// Lock and unlock.
// Defer entirely to Native Client.
// The expense of a call into Native Client is more like
// a function call than a system call, so as long as the
// Native Client lock implementation is good, we can't
// do better ourselves.

static void
xlock(int32 fd)
{
	if(mutex_lock(fd) < 0) {
		printf("mutex_lock failed\n");
		breakpoint();
	}
}

static void
xunlock(int32 fd)
{
	if(mutex_unlock(fd) < 0) {
		printf("mutex_lock failed\n");
		breakpoint();
	}
}

void
lock(Lock *l)
{
	if(m->locks < 0)
		throw("lock count");
	m->locks++;
	if(l->sema == 0)
		initsema(&l->sema);
	xlock(l->sema>>1);
}

void
unlock(Lock *l)
{
	m->locks--;
	if(m->locks < 0)
		throw("lock count");
	xunlock(l->sema>>1);
}


// One-time notifications.
//
// Since the lock/unlock implementation already
// takes care of sleeping in the kernel, we just reuse it.
// (But it's a weird use, so it gets its own interface.)
//
// We use a lock to represent the event:
// unlocked == event has happened.
// Thus the lock starts out locked, and to wait for the
// event you try to lock the lock.  To signal the event,
// you unlock the lock.
//
// Native Client does not require that the thread acquiring
// a lock be the thread that releases the lock, so this is safe.

void
noteclear(Note *n)
{
	if(n->lock.sema == 0)
		initsema(&n->lock.sema);
	xlock(n->lock.sema>>1);
}

void
notewakeup(Note *n)
{
	if(n->lock.sema == 0) {
		printf("notewakeup without noteclear");
		breakpoint();
	}
	xunlock(n->lock.sema>>1);
}

void
notesleep(Note *n)
{
	if(n->lock.sema == 0) {
		printf("notesleep without noteclear");
		breakpoint();
	}
	xlock(n->lock.sema>>1);
	xunlock(n->lock.sema>>1);	// Let other sleepers find out too.
}

void
newosproc(M *m, G *g, void *stk, void (*fn)(void))
{
	void **vstk;

	// I wish every OS made thread creation this easy.
	m->tls[0] = (uint32)g;
	m->tls[1] = (uint32)m;
	vstk = stk;
	*--vstk = nil;
	if(thread_create(fn, vstk, m->tls, sizeof m->tls) < 0) {
		printf("thread_create failed\n");
		breakpoint();
	}
}

void
osinit(void)
{
}

// Called to initialize a new m (including the bootstrap m).
void
minit(void)
{
}
